tcms.testruns.views   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 306
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 17
eloc 209
dl 0
loc 306
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A GetTestRunView.get_context_data() 0 46 1
A SearchTestRunView.get_context_data() 0 6 1
A EditTestRunView.get_form() 0 5 1
B NewTestRunView.post() 0 55 5
A EditTestRunView.get_context_data() 0 4 1
A NewTestRunView.get() 0 31 4
A EditTestRunView.get_initial() 0 4 1
A CloneTestRunView.get() 0 19 1
A GetEnvironment.get_context_data() 0 34 1

1 Function

Rating   Name   Duplication   Size   Complexity  
A get_disabled_test_cases_count() 0 2 1
1
# -*- coding: utf-8 -*-
2
3
from django.contrib.auth import get_user_model
4
from django.contrib.auth.decorators import permission_required
5
from django.core.exceptions import ObjectDoesNotExist
6
from django.http import HttpResponseRedirect
7
from django.shortcuts import get_object_or_404, render
8
from django.urls import reverse
9
from django.utils.decorators import method_decorator
10
from django.utils.translation import gettext_lazy as _
11
from django.views.generic import DetailView
12
from django.views.generic.base import TemplateView, View
13
from django.views.generic.edit import UpdateView
14
from guardian.decorators import permission_required as object_permission_required
15
16
from tcms.core.contrib.linkreference.forms import LinkReferenceForm
17
from tcms.core.forms import SimpleCommentForm
18
from tcms.testcases.models import BugSystem, TestCase, TestCasePlan, TestCaseStatus
19
from tcms.testplans.models import TestPlan
20
from tcms.testruns.forms import NewRunForm, SearchRunForm
21
from tcms.testruns.models import (
22
    Environment,
23
    EnvironmentProperty,
24
    TestExecutionStatus,
25
    TestRun,
26
)
27
28
User = get_user_model()  # pylint: disable=invalid-name
29
30
31
@method_decorator(permission_required("testruns.add_testrun"), name="dispatch")
32
class NewTestRunView(View):
33
    """Display new test run page."""
34
35
    template_name = "testruns/mutable.html"
36
    http_method_names = ["post", "get"]
37
38
    def get(self, request, form_initial=None, is_cloning=False):
39
        plan_id = request.GET.get("p")
40
41
        # note: ordered by pk for test_show_create_new_run_page()
42
        test_cases = (
43
            TestCase.objects.filter(pk__in=request.GET.getlist("c"))
44
            .select_related("author", "case_status", "category", "priority")
45
            .order_by("pk")
46
        )
47
48
        test_plan = TestPlan.objects.filter(pk=plan_id).first()
49
        if not form_initial:
50
            form_initial = {
51
                "summary": f"Test run for {test_plan.name}" if test_plan else "",
52
                "manager": test_plan.author.email if test_plan else "",
53
                "default_tester": request.user.email,
54
                "notes": "",
55
                "plan": plan_id,
56
            }
57
58
        form = NewRunForm(initial=form_initial)
59
        form.populate(plan_id)
60
61
        context_data = {
62
            "plan_id": plan_id,  # used for UI conditionals
63
            "test_cases": test_cases,
64
            "form": form,
65
            "disabled_cases": get_disabled_test_cases_count(test_cases),
66
            "is_cloning": is_cloning,
67
        }
68
        return render(request, self.template_name, context_data)
69
70
    def post(self, request):
71
        form = NewRunForm(data=request.POST)
72
        form.populate(request.POST.get("plan"))
73
74
        if form.is_valid():
75
            test_run = form.save()
76
77
            # copy all of the selected properties into the test run
78
            for prop in EnvironmentProperty.objects.filter(
79
                environment__in=form.cleaned_data["environment"]
80
            ):
81
                test_run.property_set.create(name=prop.name, value=prop.value)
82
83
            loop = 1
84
85
            for case in form.cleaned_data["case"]:
86
                try:
87
                    tcp = TestCasePlan.objects.get(
88
                        plan=form.cleaned_data["plan"], case=case
89
                    )
90
                    sortkey = tcp.sortkey
91
                except ObjectDoesNotExist:
92
                    sortkey = loop * 10
93
94
                test_run.create_execution(
95
                    case=case,
96
                    assignee=form.cleaned_data["default_tester"],
97
                    sortkey=sortkey,
98
                    matrix_type=form.cleaned_data["matrix_type"],
99
                )
100
                loop += 1
101
102
            return HttpResponseRedirect(
103
                reverse(
104
                    "testruns-get",
105
                    args=[
106
                        test_run.pk,
107
                    ],
108
                )
109
            )
110
111
        test_cases = (
112
            TestCase.objects.filter(pk__in=request.POST.getlist("case"))
113
            .select_related("author", "case_status", "category", "priority")
114
            .order_by("pk")
115
        )
116
117
        context_data = {
118
            "plan_id": request.POST.get("plan"),
119
            "test_cases": test_cases,
120
            "form": form,
121
            "disabled_cases": get_disabled_test_cases_count(test_cases),
122
        }
123
124
        return render(request, self.template_name, context_data)
125
126
127
@method_decorator(permission_required("testruns.view_testrun"), name="dispatch")
128
class SearchTestRunView(TemplateView):
129
130
    template_name = "testruns/search.html"
131
132
    def get_context_data(self, **kwargs):
133
        form = SearchRunForm(self.request.GET)
134
        form.populate(product_id=self.request.GET.get("product"))
135
136
        return {
137
            "form": form,
138
        }
139
140
141
@method_decorator(
142
    object_permission_required(
143
        "testruns.view_testrun", (TestRun, "pk", "pk"), accept_global_perms=True
144
    ),
145
    name="dispatch",
146
)
147
class GetTestRunView(DetailView):
148
149
    template_name = "testruns/get.html"
150
    http_method_names = ["get"]
151
    model = TestRun
152
153
    def get_context_data(self, **kwargs):
154
        context = super().get_context_data(**kwargs)
155
        context["execution_statuses"] = TestExecutionStatus.objects.order_by(
156
            "-weight", "name"
157
        )
158
        context["confirmed_statuses"] = TestCaseStatus.objects.filter(is_confirmed=True)
159
        context["link_form"] = LinkReferenceForm()
160
        context["bug_trackers"] = BugSystem.objects.all()
161
        context["comment_form"] = SimpleCommentForm()
162
        context["OBJECT_MENU_ITEMS"] = [
163
            (
164
                "...",
165
                [
166
                    (
167
                        _("Edit"),
168
                        reverse("testruns-edit", args=[self.object.pk]),
169
                    ),
170
                    (
171
                        _("Clone"),
172
                        reverse("testruns-clone", args=[self.object.pk]),
173
                    ),
174
                    (
175
                        _("History"),
176
                        f"/admin/testruns/testrun/{self.object.pk}/history/",
177
                    ),
178
                    ("-", "-"),
179
                    (
180
                        _("Object permissions"),
181
                        reverse(
182
                            "admin:testruns_testrun_permissions",
183
                            args=[self.object.pk],
184
                        ),
185
                    ),
186
                    ("-", "-"),
187
                    (
188
                        _("Delete"),
189
                        reverse(
190
                            "admin:testruns_testrun_delete",
191
                            args=[self.object.pk],
192
                        ),
193
                    ),
194
                ],
195
            )
196
        ]
197
198
        return context
199
200
201
@method_decorator(
202
    object_permission_required(
203
        "testruns.change_testrun", (TestRun, "pk", "pk"), accept_global_perms=True
204
    ),
205
    name="dispatch",
206
)
207
class EditTestRunView(UpdateView):
208
    model = TestRun
209
    template_name = "testruns/mutable.html"
210
    form_class = NewRunForm
211
212
    def get_form(self, form_class=None):
213
        form = super().get_form(form_class)
214
        form.populate(self.object.plan_id)
215
216
        return form
217
218
    def get_context_data(self, **kwargs):
219
        context = super().get_context_data(**kwargs)
220
        context["plan_id"] = self.object.plan
221
        return context
222
223
    def get_initial(self):
224
        return {
225
            "manager": self.object.manager,
226
            "default_tester": self.object.default_tester,
227
        }
228
229
230
@method_decorator(permission_required("testruns.add_testrun"), name="dispatch")
231
class CloneTestRunView(NewTestRunView):
232
    # note: post is handled directly by NewTestRunView
233
    # b/c <form action> points to testruns-new URL
234
    http_method_names = ["get"]
235
236
    def get(self, request, pk):  # pylint: disable=arguments-differ
237
        test_run = get_object_or_404(TestRun, pk=pk)
238
239
        request.GET._mutable = True  # pylint: disable=protected-access
240
        request.GET["p"] = test_run.plan_id
241
        request.GET.setlist(
242
            "c", test_run.executions.all().values_list("case", flat=True)
243
        )
244
245
        form_initial = {
246
            "summary": _("Clone of ") + test_run.summary,
247
            "notes": test_run.notes,
248
            "manager": test_run.manager,
249
            "build": test_run.build_id,
250
            "default_tester": test_run.default_tester,
251
            "plan": test_run.plan_id,
252
        }
253
254
        return super().get(request, form_initial=form_initial, is_cloning=True)
255
256
257
def get_disabled_test_cases_count(test_cases):
258
    return test_cases.filter(case_status__is_confirmed=False).count()
259
260
261
@method_decorator(
262
    object_permission_required(
263
        "testruns.view_environment", (Environment, "pk", "pk"), accept_global_perms=True
264
    ),
265
    name="dispatch",
266
)
267
class GetEnvironment(DetailView):
268
    template_name = "testruns/environment.html"
269
    http_method_names = ["get"]
270
    model = Environment
271
272
    def get_context_data(self, **kwargs):
273
        context = super().get_context_data(**kwargs)
274
        context["OBJECT_MENU_ITEMS"] = [
275
            (
276
                "...",
277
                [
278
                    (
279
                        _("Edit"),
280
                        reverse(
281
                            "admin:testruns_environment_change",
282
                            args=[self.object.pk],
283
                        ),
284
                    ),
285
                    ("-", "-"),
286
                    (
287
                        _("Object permissions"),
288
                        reverse(
289
                            "admin:testruns_environment_permissions",
290
                            args=[self.object.pk],
291
                        ),
292
                    ),
293
                    ("-", "-"),
294
                    (
295
                        _("Delete"),
296
                        reverse(
297
                            "admin:testruns_environment_delete",
298
                            args=[self.object.pk],
299
                        ),
300
                    ),
301
                ],
302
            )
303
        ]
304
305
        return context
306