Skip to content

Commit 40e85d2

Browse files
committed
(api) Make duration fields available as filters in the /cases/search/ page
Refs #1923
1 parent b0e2151 commit 40e85d2

File tree

5 files changed

+124
-1
lines changed

5 files changed

+124
-1
lines changed

tcms/rpc/api/testcase.py

+11
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,20 @@ def filter(query=None): # pylint: disable=redefined-builtin
279279
:return: Serialized list of :class:`tcms.testcases.models.TestCase` objects.
280280
:rtype: list(dict)
281281
"""
282+
from django.utils.dateparse import parse_duration
283+
282284
if query is None:
283285
query = {}
284286

287+
if "setup_duration" in query:
288+
query["setup_duration"] = parse_duration(query["setup_duration"])
289+
290+
if "testing_duration" in query:
291+
query["testing_duration"] = parse_duration(query["testing_duration"])
292+
293+
if "expected_duration" in query:
294+
query["expected_duration"] = parse_duration(query["expected_duration"])
295+
285296
qs = (
286297
TestCase.objects.annotate(
287298
expected_duration=Coalesce("setup_duration", timedelta(0))

tcms/rpc/tests/test_testcase.py

+29
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,35 @@ def test_duration_properties_in_result(
223223
self.assertEqual(result[0]["testing_duration"], testing_duration)
224224
self.assertEqual(result[0]["expected_duration"], expected_duration)
225225

226+
def test_filter_by_setup_duration(self):
227+
case = TestCaseFactory(setup_duration=timedelta(seconds=45))
228+
229+
result = self.rpc_client.TestCase.filter({"setup_duration": "0:00:45"})
230+
231+
self.assertIsNotNone(result)
232+
self.assertEqual(len(result), 1)
233+
self.assertEqual(result[0]["id"], case.pk)
234+
235+
def test_filter_by_testing_duration(self):
236+
case = TestCaseFactory(testing_duration=timedelta(minutes=2))
237+
238+
result = self.rpc_client.TestCase.filter({"testing_duration": "0:02:00"})
239+
240+
self.assertIsNotNone(result)
241+
self.assertEqual(len(result), 1)
242+
self.assertEqual(result[0]["id"], case.pk)
243+
244+
def test_filter_by_expected_duration(self):
245+
case = TestCaseFactory(
246+
setup_duration=timedelta(seconds=45), testing_duration=timedelta(minutes=2)
247+
)
248+
249+
result = self.rpc_client.TestCase.filter({"expected_duration": "0:02:45"})
250+
251+
self.assertIsNotNone(result)
252+
self.assertEqual(len(result), 1)
253+
self.assertEqual(result[0]["id"], case.pk)
254+
226255

227256
class TestUpdate(APITestCase):
228257
non_existing_username = "FakeUsername"

tcms/testcases/forms.py

+12
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ class Meta:
124124
widget=forms.CheckboxSelectMultiple(),
125125
required=False,
126126
)
127+
setup_duration = forms.DurationField(
128+
widget=DurationWidget(),
129+
required=False,
130+
)
131+
testing_duration = forms.DurationField(
132+
widget=DurationWidget(),
133+
required=False,
134+
)
135+
expected_duration = forms.DurationField(
136+
widget=DurationWidget(),
137+
required=False,
138+
)
127139

128140
def populate(self, product_id=None):
129141
if product_id:

tcms/testcases/static/testcases/js/search.js

+46-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ function pre_process_data (data, callback) {
5252
})
5353
}
5454

55+
function formatDuration(seconds) {
56+
let numSecondsInDay = 24 * 60 * 60;
57+
let days = Math.floor(seconds / numSecondsInDay);
58+
let rest = seconds % numSecondsInDay;
59+
60+
let date = new Date(0);
61+
date.setSeconds(rest);
62+
let timeString = date.toISOString().substr(11, 8);
63+
64+
if (days) {
65+
return `${days} ${timeString}`;
66+
}
67+
return `${timeString}`;
68+
}
69+
5570
$(document).ready(function () {
5671
const table = $('#resultsTable').DataTable({
5772
pageLength: $('#navbar').data('defaultpagesize'),
@@ -106,6 +121,18 @@ $(document).ready(function () {
106121
params.is_automated = false
107122
};
108123

124+
if (!['', '0'].includes($('#id_setup_duration').val())) {
125+
params.setup_duration = $('#id_setup_duration').val()
126+
};
127+
128+
if (!['', '0'].includes($('#id_testing_duration').val())) {
129+
params.testing_duration = $('#id_testing_duration').val()
130+
};
131+
132+
if (!['', '0'].includes($('#id_expected_duration').val())) {
133+
params.expected_duration = $('#id_expected_duration').val()
134+
};
135+
109136
const text = $('#id_text').val()
110137
if (text) {
111138
params.text__icontains = text
@@ -145,7 +172,25 @@ $(document).ready(function () {
145172
{ data: 'case_status__name' },
146173
{ data: 'is_automated' },
147174
{ data: 'author__username' },
148-
{ data: 'tag_names' }
175+
{ data: 'tag_names' },
176+
{
177+
data: 'setup_duration',
178+
render: function(data, type, full, meta) {
179+
return formatDuration(data);
180+
}
181+
},
182+
{
183+
data: 'testing_duration',
184+
render: function(data, type, full, meta) {
185+
return formatDuration(data);
186+
}
187+
},
188+
{
189+
data: 'expected_duration',
190+
render: function(data, type, full, meta) {
191+
return formatDuration(data);
192+
}
193+
}
149194
],
150195
dom: 't',
151196
language: {

tcms/testcases/templates/testcases/search.html

+26
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
{% load i18n %}
33
{% load static %}
44

5+
{% block head %}
6+
{{ form.media }}
57
{% block title %}{% trans "Search test cases" %}{% endblock %}
8+
{% endblock %}
69

710
{% block contents %}
811
<div class="container-fluid container-cards-pf">
@@ -128,6 +131,29 @@
128131

129132
</div>
130133

134+
<div class="form-group">
135+
<label class="col-md-1 col-lg-1">{% trans "Setup duration" %}</label>
136+
<div class="col-md-3 col-lg-3">
137+
<div id="setup_duration">
138+
{{ form.setup_duration }}
139+
</div>
140+
</div>
141+
142+
<label class="col-md-1 col-lg-1">{% trans "Testing duration" %}</label>
143+
<div class="col-md-3 col-lg-3">
144+
<div id="testing-duration">
145+
{{ form.testing_duration }}
146+
</div>
147+
</div>
148+
149+
<label class="col-md-1 col-lg-1">{% trans "Expected duration" %}</label>
150+
<div class="col-md-3 col-lg-3">
151+
<div id="expected-duration">
152+
{{ form.expected_duration }}
153+
</div>
154+
</div>
155+
</div>
156+
131157
<div class="form-group">
132158
<div class="col-md-1 col-lg-1">
133159
<button id="btn_search" type="submit" class="btn btn-default btn-lg">{% trans "Search" %}</button>

0 commit comments

Comments
 (0)