11from datetime import datetime
2+ from ftw .builder import Builder
3+ from ftw .builder import create
24from ftw .testbrowser import browsing
35from ftw .testing import freeze
46from opengever .dossier .resolve import LockingResolveManager
57from opengever .testing import IntegrationTestCase
68from plone import api
9+ import json
710
811
912class TestDossierWorkflowRESTAPITransitions (IntegrationTestCase ):
@@ -21,12 +24,14 @@ def assert_state(self, expected_state, obj):
2124 self .assertEquals (expected_state ,
2225 api .content .get_state (obj ))
2326
24- def api_transition (self , obj , transition , browser ):
27+ def api_transition (self , obj , transition , browser , data = None ):
2528 url = '/' .join ((obj .absolute_url (), '@workflow' , transition ))
2629 browser .open (
2730 url ,
28- headers = {'Accept' : 'application/json' },
29- method = 'POST' )
31+ headers = self .api_headers ,
32+ method = 'POST' ,
33+ data = data
34+ )
3035
3136 @browsing
3237 def test_resolve_via_restapi (self , browser ):
@@ -199,3 +204,118 @@ def test_archive_offered_via_restapi_is_forbidden(self, browser):
199204 {u'message' : u"Invalid transition 'dossier-transition-archive'.\n Valid transitions are:\n " ,
200205 u'type' : u'Bad Request' }},
201206 browser .json )
207+
208+ @browsing
209+ def test_resolve_dossier_auto_close_tasks (self , browser ):
210+
211+ self .login (self .secretariat_user , browser )
212+
213+ open_task = create (
214+ Builder ('task' )
215+ .within (self .resolvable_subdossier )
216+ .in_state ('task-state-open' )
217+ .titled (u'Task 1' )
218+ .having (
219+ issuer = self .secretariat_user .id ,
220+ responsible = self .secretariat_user .id ,
221+ responsible_client = 'fa' ,
222+ )
223+ )
224+ in_progress_task = create (
225+ Builder ('task' )
226+ .within (self .resolvable_subdossier )
227+ .in_state ('task-state-in-progress' )
228+ .titled (u'Task 2' )
229+ .having (
230+ issuer = self .secretariat_user .id ,
231+ responsible = self .secretariat_user .id ,
232+ responsible_client = 'fa' ,
233+ task_type = 'approval' ,
234+ )
235+ )
236+ resolved_task = create (
237+ Builder ('task' )
238+ .within (self .resolvable_subdossier )
239+ .in_state ('task-state-resolved' )
240+ .titled (u'Task 3' )
241+ .having (
242+ issuer = self .secretariat_user .id ,
243+ responsible = self .secretariat_user .id ,
244+ responsible_client = 'fa' ,
245+ )
246+ )
247+ with freeze (datetime (2018 , 4 , 30 )):
248+ with browser .expect_http_error ():
249+ self .api_transition (self .resolvable_subdossier , 'dossier-transition-resolve' , browser )
250+ self .assertEqual (400 , browser .status_code )
251+ self .assertDictEqual (
252+ {
253+ u'error' : {
254+ u'message' : u'' ,
255+ u'errors' : [u'not all task are closed' ],
256+ u'type' : u'PreconditionsViolated' ,
257+ u'has_not_closed_tasks' : True ,
258+ }
259+ },
260+ browser .json )
261+
262+ # dossier and tasks state did not change
263+ self .assert_state ('dossier-state-active' , self .resolvable_subdossier )
264+
265+ self .assert_state ('task-state-open' , open_task )
266+ self .assert_state ('task-state-in-progress' , in_progress_task )
267+ self .assert_state ('task-state-resolved' , resolved_task )
268+
269+ with freeze (datetime (2018 , 4 , 30 )):
270+
271+ self .api_transition (
272+ self .resolvable_subdossier ,
273+ 'dossier-transition-resolve' ,
274+ browser ,
275+ data = json .dumps ({"auto_close_tasks" : True })
276+ )
277+
278+ self .assertEqual (200 , browser .status_code )
279+
280+ # dossier and tasks states were changed
281+ self .assert_state ('dossier-state-resolved' , self .resolvable_subdossier )
282+
283+ self .assert_state ('task-state-cancelled' , open_task )
284+ self .assert_state ('task-state-tested-and-closed' , in_progress_task )
285+ self .assert_state ('task-state-tested-and-closed' , resolved_task )
286+
287+ @browsing
288+ def test_resolve_dossier_auto_close_tasks_raises_error_if_auto_close_is_not_possible (self , browser ):
289+ self .login (self .secretariat_user , browser )
290+
291+ # A private task cannot be closed by the secretarian user.
292+ # The api should raise an error in this case.
293+ create (
294+ Builder ('task' )
295+ .within (self .resolvable_dossier )
296+ .in_state ('task-state-open' )
297+ .titled (u'Task 1' )
298+ .having (
299+ issuer = self .regular_user .id ,
300+ responsible = self .regular_user .id ,
301+ responsible_client = 'fa' ,
302+ is_private = True ,
303+ )
304+ )
305+
306+ with browser .expect_http_error (code = 400 ):
307+ self .api_transition (
308+ self .resolvable_dossier ,
309+ 'dossier-transition-resolve' ,
310+ browser ,
311+ data = json .dumps ({"auto_close_tasks" : True })
312+ )
313+
314+ self .assertEqual (
315+ {
316+ u'error' : {
317+ u'errors' : [u'Auto-close tasks is not possible. Please close the tasks manually.' ],
318+ u'type' : u'AutoCloseTasksNotPossible'
319+ }
320+ },
321+ browser .json )
0 commit comments