Passed
Push — master ( bd2622...f167a9 )
by Paolo
06:51
created

FetchWithErrorsTestCase.test_validationresult()   A

Complexity

Conditions 1

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 18
rs 9.9
c 0
b 0
f 0
cc 1
nop 1
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Tue Oct  9 14:51:13 2018
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
from pytest import raises
10
from collections import Counter
11
from unittest.mock import patch, Mock
12
from datetime import timedelta
13
from pyUSIrest.exceptions import USIConnectionError
14
15
from celery.exceptions import Retry
16
17
from django.test import TestCase
18
from django.core import mail
19
from django.db.models import F
20
from django.utils import timezone
21
22
from common.constants import (
23
    LOADED, ERROR, READY, NEED_REVISION, SUBMITTED, COMPLETED, STATUSES)
24
from common.tests import WebSocketMixin
25
from uid.models import Submission, Animal, Sample
26
from validation.models import ValidationResult, ValidationSummary
27
28
from ..tasks.retrieval import (
29
    FetchStatusTask, FetchStatusHelper, RetrievalCompleteTask)
30
from ..models import ManagedTeam, Submission as USISubmission
31
32
33
class FetchMixin():
34
    """Mixin for fetching status"""
35
36
    fixtures = [
37
        'biosample/account',
38
        'biosample/managedteam',
39
        'biosample/submission',
40
        'biosample/submissiondata',
41
        'biosample/validationresult',
42
        'biosample/validationsummary',
43
        'uid/animal',
44
        'uid/dictbreed',
45
        'uid/dictcountry',
46
        'uid/dictrole',
47
        'uid/dictsex',
48
        'uid/dictspecie',
49
        'uid/dictstage',
50
        'uid/dictuberon',
51
        'uid/organization',
52
        'uid/publication',
53
        'uid/sample',
54
        'uid/submission',
55
        'uid/user'
56
    ]
57
58
    @classmethod
59
    def setUpClass(cls):
60
        # calling my base class setup
61
        super().setUpClass()
62
63
        unmanaged = ManagedTeam.objects.get(pk=2)
64
        unmanaged.delete()
65
66
        # starting mocked objects
67
        cls.mock_root_patcher = patch('pyUSIrest.usi.Root')
68
        cls.mock_root = cls.mock_root_patcher.start()
69
70
        cls.mock_auth_patcher = patch('pyUSIrest.auth.Auth')
71
        cls.mock_auth = cls.mock_auth_patcher.start()
72
73
    @classmethod
74
    def tearDownClass(cls):
75
        cls.mock_root_patcher.stop()
76
        cls.mock_auth_patcher.stop()
77
78
        # calling base method
79
        super().tearDownClass()
80
81
    def setUp(self):
82
        # calling my base setup
83
        super().setUp()
84
85
        # get a submission object
86
        self.submission_obj = Submission.objects.get(pk=1)
87
88
        # set a status which I can fetch_status
89
        self.submission_obj.status = SUBMITTED
90
        self.submission_obj.message = "Waiting for biosample validation"
91
        self.submission_obj.save()
92
93
        # set status for objects, like submittask does.
94
        self.animal_qs = Animal.objects.all()
95
        self.animal_qs.update(status=SUBMITTED)
96
97
        self.sample_qs = Sample.objects.all()
98
        self.sample_qs.update(status=SUBMITTED)
99
100
        # count number of names in UID for such submission (exclude
101
        # unknown animals)
102
        self.n_to_submit = self.animal_qs.count() + self.sample_qs.count()
103
104
        # track submission ID
105
        self.submission_obj_id = self.submission_obj.id
106
107
        # start root object
108
        self.my_root = self.mock_root.return_value
109
110
    def count_by_status(self, status):
111
        """Return the number of sample and animal by status"""
112
113
        return (
114
            Animal.objects.filter(status=status).count() +
115
            Sample.objects.filter(status=status).count()
116
        )
117
118
119
class FetchStatusHelperMixin(FetchMixin):
120
    """Test class for FetchStatusHelper"""
121
122
    def setUp(self):
123
        # calling my base setup
124
        super().setUp()
125
126
        # define a biosample submission object
127
        self.my_submission = Mock()
128
        self.my_submission.name = "test-fetch"
129
130
        # passing submission to Mocked Root
131
        self.my_root.get_submission_by_name.return_value = self.my_submission
132
133
        # get a biosample.model.Submission and update object
134
        self.usi_submission = USISubmission.objects.get(pk=1)
135
        self.usi_submission.usi_submission_name = self.my_submission.name
136
        self.usi_submission.status = SUBMITTED
137
        self.usi_submission.save()
138
139
        # ok setup the object
140
        self.status_helper = FetchStatusHelper(self.usi_submission)
141
142
        # track names
143
        self.animal = Animal.objects.get(pk=1)
144
        self.sample = Sample.objects.get(pk=1)
145
146
    def common_tests(self):
147
        """Assert stuff for each test"""
148
149
        # call stuff
150
        self.status_helper.check_submission_status()
151
152
        # UID submission status remain the same
153
        self.submission_obj.refresh_from_db()
154
        self.assertEqual(self.submission_obj.status, SUBMITTED)
155
156
        self.assertTrue(self.mock_auth.called)
157
        self.assertTrue(self.mock_root.called)
158
        self.assertTrue(self.my_root.get_submission_by_name.called)
159
160
161
class FetchIgnoreTestCase(FetchStatusHelperMixin, TestCase):
162
    """a submission that could be ignored"""
163
164
    def setUp(self):
165
        # calling my base setup
166
        super().setUp()
167
168
        # an unmanaged status
169
        self.my_submission.status = 'Unmanaged'
170
171
    def common_tests(self, status):
172
        """Override default common tests. Status is the status the
173
        submission is supposed to remain"""
174
175
        # assert auth, root and get_submission by name called
176
        super().common_tests()
177
178
        # USI submission status did't changed
179
        self.usi_submission.refresh_from_db()
180
        self.assertEqual(self.usi_submission.status, status)
181
182
        # check animal/sample status didn't changed
183
        n_to_submit = self.count_by_status(SUBMITTED)
184
        self.assertEqual(n_to_submit, self.n_to_submit)
185
186
    def test_fetch_unmanaged_submission_status(self):
187
        """Test fetch status for an unmanaged submission"""
188
189
        # assert my common tests
190
        self.common_tests(status=SUBMITTED)
191
192
    def test_fetch_not_submitted(self):
193
        """Ignore a submission with a status different from SUBMITTED"""
194
195
        self.usi_submission.status = COMPLETED
196
        self.usi_submission.save()
197
198
        self.common_tests(status=COMPLETED)
199
200
201
class FetchCompletedTestCase(FetchStatusHelperMixin, TestCase):
202
    """a completed submission with two samples"""
203
204
    def setUp(self):
205
        # calling my base setup
206
        super().setUp()
207
208
        # a completed submission with two samples
209
        self.my_submission.status = 'Completed'
210
211
    def test_fetch_status(self):
212
        """Test fetch status for a complete submission"""
213
214
        # Add samples
215
        my_sample1 = Mock()
216
        my_sample1.name = "test-animal"
217
        my_sample1.alias = "IMAGEA000000001"
218
        my_sample1.accession = "SAMEA0000001"
219
        my_sample2 = Mock()
220
        my_sample2.name = "test-sample"
221
        my_sample2.alias = "IMAGES000000001"
222
        my_sample2.accession = "SAMEA0000002"
223
        self.my_submission.get_samples.return_value = [my_sample1, my_sample2]
224
225
        # assert auth, root and get_submission by name called
226
        self.common_tests()
227
228
        # USI submission status changed
229
        self.usi_submission.refresh_from_db()
230
        self.assertEqual(self.usi_submission.status, COMPLETED)
231
232
        # check name status changed
233
        n_completed = self.count_by_status(COMPLETED)
234
        self.assertEqual(n_completed, 2)
235
236
        # fetch two name objects
237
        self.animal.refresh_from_db()
238
        self.assertEqual(self.animal.biosample_id, "SAMEA0000001")
239
240
        self.sample.refresh_from_db()
241
        self.assertEqual(self.sample.biosample_id, "SAMEA0000002")
242
243
    def test_fetch_status_no_accession(self):
244
        """Test fetch status for a submission which doens't send accession
245
        no updates in such case"""
246
247
        # Add samples
248
        my_sample1 = Mock()
249
        my_sample1.name = "test-animal"
250
        my_sample1.alias = "IMAGEA000000001"
251
        my_sample1.accession = None
252
        my_sample2 = Mock()
253
        my_sample2.name = "test-sample"
254
        my_sample2.alias = "IMAGES000000001"
255
        my_sample2.accession = None
256
        self.my_submission.get_samples.return_value = [my_sample1, my_sample2]
257
258
        # assert auth, root and get_submission by name called
259
        self.common_tests()
260
261
        # USI submission status didn't change
262
        self.usi_submission.refresh_from_db()
263
        self.assertEqual(self.usi_submission.status, SUBMITTED)
264
265
        # check name status didn't changed
266
        n_to_submit = self.count_by_status(SUBMITTED)
267
        self.assertEqual(n_to_submit, self.n_to_submit)
268
269
270
class FetchWithErrorsTestCase(FetchStatusHelperMixin, TestCase):
271
    """Test a submission with errors for biosample"""
272
273
    def setUp(self):
274
        # calling my base setup
275
        super().setUp()
276
277
        # a draft submission with errors
278
        self.my_submission.status = 'Draft'
279
        self.my_submission.has_errors.return_value = Counter(
280
            {True: 1, False: 1})
281
        self.my_submission.get_status.return_value = Counter({'Complete': 2})
282
283
        # Add samples. Suppose that first failed, second is ok
284
        my_validation_result1 = Mock()
285
        my_validation_result1.errorMessages = {
286
            'Ena': [
287
                'a sample message',
288
            ]
289
        }
290
291
        my_sample1 = Mock()
292
        my_sample1.name = "test-animal"
293
        my_sample1.alias = "IMAGEA000000001"
294
        my_sample1.has_errors.return_value = True
295
        my_sample1.get_validation_result.return_value = my_validation_result1
296
297
        # sample2 is ok
298
        my_validation_result2 = Mock()
299
        my_validation_result2.errorMessages = None
300
301
        my_sample2 = Mock()
302
        my_sample2.name = "test-sample"
303
        my_sample2.alias = "IMAGES000000001"
304
        my_sample2.has_errors.return_value = False
305
        my_sample2.get_validation_result.return_value = my_validation_result2
306
307
        # simulate that IMAGEA000000001 has errors
308
        self.my_submission.get_samples.return_value = [my_sample1, my_sample2]
309
310
        # track other objects
311
        self.my_sample1 = my_sample1
312
        self.my_sample2 = my_sample2
313
314
    def common_tests(self):
315
        # assert auth, root and get_submission by name called
316
        super().common_tests()
317
318
        # assert custom mock attributes called
319
        self.assertTrue(self.my_sample1.has_errors.called)
320
        self.assertTrue(self.my_sample1.get_validation_result.called)
321
322
        # if sample has no errors, no all methods will be called
323
        self.assertTrue(self.my_sample2.has_errors.called)
324
        self.assertFalse(self.my_sample2.get_validation_result.called)
325
326
    def test_fetch_status(self):
327
        # assert mock methods called
328
        self.common_tests()
329
330
        # USI submission changed
331
        self.usi_submission.refresh_from_db()
332
        self.assertEqual(self.usi_submission.status, NEED_REVISION)
333
334
        # check name status changed only for animal (not sample)
335
        self.animal.refresh_from_db()
336
        self.assertEqual(self.animal.status, NEED_REVISION)
337
338
        self.sample.refresh_from_db()
339
        self.assertEqual(self.sample.status, SUBMITTED)
340
341
    def test_validationresult(self):
342
        # assert auth, root and get_submission by name called
343
        super().common_tests()
344
345
        # reload object from database
346
        self.animal.validationresult.refresh_from_db()
347
        self.sample.validationresult.refresh_from_db()
348
349
        # ok check error messages
350
        self.assertEqual(self.animal.validationresult.status, "Error")
351
        self.assertEqual(self.sample.validationresult.status, "Pass")
352
353
        # a check on error messages
354
        messages = ["Ena: ['a sample message']"]
355
        self.assertListEqual(self.animal.validationresult.messages, messages)
356
357
        messages = []
358
        self.assertListEqual(self.sample.validationresult.messages, messages)
359
360
    def test_validationsummary(self):
361
        # assert auth, root and get_submission by name called
362
        super().common_tests()
363
364
        # get the two validationsummary objects
365
        summary = self.submission_obj.validationsummary_set.filter(
366
            type='animal').first()
367
368
        # assert values
369
        summary.refresh_from_db()
370
        self.assertEqual(summary.pass_count, 2)
371
        self.assertEqual(summary.error_count, 1)
372
        self.assertEqual(summary.issues_count, 1)
373
374
        summary = self.submission_obj.validationsummary_set.filter(
375
            type='sample').first()
376
377
        # assert values
378
        summary.refresh_from_db()
379
        self.assertEqual(summary.pass_count, 1)
380
        self.assertEqual(summary.error_count, 0)
381
        self.assertEqual(summary.issues_count, 0)
382
383
384
class FetchDraftTestCase(FetchStatusHelperMixin, TestCase):
385
    """a draft submission without errors"""
386
387
    def common_tests(self):
388
        # assert auth, root and get_submission by name called
389
        super().common_tests()
390
391
        # USI submission status didn't change
392
        self.usi_submission.refresh_from_db()
393
        self.assertEqual(self.usi_submission.status, SUBMITTED)
394
395
    def test_fetch_status(self):
396
        # a draft submission without errors
397
        self.my_submission.status = 'Draft'
398
        self.my_submission.has_errors.return_value = Counter({False: 2})
399
        self.my_submission.get_status.return_value = Counter({'Complete': 2})
400
401
        # assert mock methods called
402
        self.common_tests()
403
404
        # testing a finalized biosample condition
405
        self.assertTrue(self.my_submission.finalize.called)
406
407
    def test_fetch_status_pending(self):
408
        """Testing status with pending validation"""
409
410
        # a draft submission without errors
411
        self.my_submission.status = 'Draft'
412
        self.my_submission.has_errors.return_value = Counter({False: 2})
413
        self.my_submission.get_status.return_value = Counter({'Pending': 2})
414
415
        # assert mock methods called
416
        self.common_tests()
417
418
        # testing a not finalized biosample condition
419
        self.assertFalse(self.my_submission.finalize.called)
420
421
    def test_fetch_status_submitted(self):
422
        """Testing status during biosample submission"""
423
424
        # a draft submission without errors
425
        self.my_submission.status = 'Submitted'
426
        self.my_submission.has_errors.return_value = Counter({False: 2})
427
        self.my_submission.get_status.return_value = Counter({'Complete': 2})
428
429
        # assert mock methods called
430
        self.common_tests()
431
432
        # testing a not finalized biosample condition
433
        self.assertFalse(self.my_submission.finalize.called)
434
435
    def test_fetch_status_processing(self):
436
        """This is a status I see during validation"""
437
438
        # an example submission in processing stage. If everything is ok
439
        # it has no errors and is complete
440
        self.my_submission.status = 'Processing'
441
        self.my_submission.has_errors.return_value = Counter({False: 2})
442
        self.my_submission.get_status.return_value = Counter({'Complete': 2})
443
444
        # assert mock methods called
445
        self.common_tests()
446
447
        # testing a not finalized biosample condition
448
        self.assertFalse(self.my_submission.finalize.called)
449
450
451
class FetchLongStatusTestCase(FetchStatusHelperMixin, TestCase):
452
    """A submission wich remain in the same status for a long time"""
453
454
    def setUp(self):
455
        # calling my base setup
456
        super().setUp()
457
458
        # make "now" 2 months ago
459
        testtime = timezone.now() - timedelta(days=60)
460
461
        # https://devblog.kogan.com/blog/testing-auto-now-datetime-fields-in-django
462
        with patch('django.utils.timezone.now') as mock_now:
463
            mock_now.return_value = testtime
464
465
            # update submission updated time with an older date than now
466
            self.usi_submission.updated_at = testtime
467
            self.usi_submission.save()
468
469
    def common_tests(self):
470
        # assert auth, root and get_submission by name called
471
        super().common_tests()
472
473
        # biosample.models.Submission status changed
474
        self.assertEqual(self.usi_submission.status, ERROR)
475
        self.assertIn(
476
            "Biosample submission '{}' remained with the same status".format(
477
                self.my_submission.name),
478
            self.usi_submission.message
479
        )
480
481
    def test_error_in_submitted_status(self):
482
        # a still running submission
483
        self.my_submission.status = 'Submitted'
484
485
        # assert mock methods called
486
        self.common_tests()
487
488
    def test_error_in_draft_status(self):
489
        # a still running submission
490
        self.my_submission.status = 'Draft'
491
492
        # assert mock methods called
493
        self.common_tests()
494
495
    def test_error_in_processing_status(self):
496
        # a still running submission
497
        self.my_submission.status = 'Processing'
498
499
        # assert mock methods called
500
        self.common_tests()
501
502
503
class FetchUnsupportedStatusTestCase(FetchMixin, TestCase):
504
    """A submission object with a status I can ignore. Task will exit
505
    immediatey"""
506
507
    def setUp(self):
508
        # calling my base setup
509
        super().setUp()
510
511
        # define my task
512
        self.my_task = FetchStatusTask()
513
514
        # change lock_id (useful when running test during cron)
515
        self.my_task.lock_id = "test-FetchStatusTask"
516
517
    def update_status(self, status):
518
        # change status
519
        self.submission_obj.status = status
520
        self.submission_obj.save()
521
522
    # override FetchMixing methods
523
    def common_tests(self, status):
524
        # update submission status
525
        self.update_status(status)
526
527
        # NOTE that I'm calling the function directly, without delay
528
        # (AsyncResult). I've patched the time consuming task
529
        res = self.my_task.run()
530
531
        # assert a success with data uploading
532
        self.assertEqual(res, "success")
533
534
        self.assertFalse(self.mock_auth.called)
535
        self.assertFalse(self.mock_root.called)
536
        self.assertFalse(self.my_root.get_submission_by_name.called)
537
538
        # assert status for submissions
539
        self.submission_obj.refresh_from_db()
540
        self.assertEqual(self.submission_obj.status, status)
541
542
    def test_loaded(self):
543
        """Test fecth_status with a loaded submission"""
544
545
        # assert task and mock methods called
546
        self.common_tests(LOADED)
547
548
    def test_need_revision(self):
549
        """Test fecth_status with a need_revision submission"""
550
551
        # assert task and mock methods called
552
        self.common_tests(NEED_REVISION)
553
554
    def test_ready(self):
555
        """Test fecth_status with a ready submission"""
556
557
        # assert task and mock methods called
558
        self.common_tests(READY)
559
560
    def test_completed(self):
561
        """Test fecth_status with a completed submission"""
562
563
        # assert task and mock methods called
564
        self.common_tests(COMPLETED)
565
566
567
class FetchStatusTaskTestCase(FetchMixin, TestCase):
568
    def setUp(self):
569
        # calling my base setup
570
        super().setUp()
571
572
        # set proper status to biosample.models.Submission
573
        USISubmission.objects.update(status=SUBMITTED)
574
575
        # starting mocked objects
576
        self.mock_helper_patcher = patch(
577
            'biosample.tasks.retrieval.FetchStatusHelper')
578
        self.mock_helper = self.mock_helper_patcher.start()
579
580
        self.mock_complete_patcher = patch(
581
            'biosample.tasks.retrieval.RetrievalCompleteTask')
582
        self.mock_complete = self.mock_complete_patcher.start()
583
584
        # define my task
585
        self.my_task = FetchStatusTask()
586
587
        # change lock_id (useful when running test during cron)
588
        self.my_task.lock_id = "test-FetchStatusTask"
589
590
    def tearDown(self):
591
        self.mock_helper_patcher.stop()
592
        self.mock_complete_patcher.stop()
593
594
        # calling base method
595
        super().tearDown()
596
597
    def test_fetch_status(self):
598
        """Test fetch status task"""
599
600
        # NOTE that I'm calling the function directly, without delay
601
        # (AsyncResult). I've patched the time consuming task
602
        res = self.my_task.run()
603
604
        # assert a success with data uploading
605
        self.assertEqual(res, "success")
606
607
        # assert my objects called
608
        self.assertTrue(self.mock_helper.called)
609
        self.assertTrue(self.mock_complete.called)
610
611
        # those objects are proper of FetchStatusHelper class, no one
612
        # call them in this task itself
613
        self.assertFalse(self.mock_auth.called)
614
        self.assertFalse(self.mock_root.called)
615
616
    def test_fetch_status_all_completed(self):
617
        """Test fetch status task with completed biosample.models.Submission"""
618
619
        # simulate completed case (no more requests to biosample)
620
        USISubmission.objects.update(status=COMPLETED)
621
622
        # NOTE that I'm calling the function directly, without delay
623
        # (AsyncResult). I've patched the time consuming task
624
        res = self.my_task.run()
625
626
        # assert a success with data uploading
627
        self.assertEqual(res, "success")
628
629
        # assert no helper called for this submission
630
        self.assertFalse(self.mock_helper.called)
631
632
        # this is called if every submission is completed
633
        self.assertTrue(self.mock_complete.called)
634
635
        # those objects are proper of FetchStatusHelper class, no one
636
        # call them in this task itself
637
        self.assertFalse(self.mock_auth.called)
638
        self.assertFalse(self.mock_root.called)
639
640
    # http://docs.celeryproject.org/en/latest/userguide/testing.html#tasks-and-unit-tests
641
    @patch("biosample.tasks.FetchStatusTask.retry")
642
    @patch("biosample.tasks.FetchStatusTask.fetch_queryset")
643
    def test_fetch_status_retry(self, my_fetch, my_retry):
644
        """Test fetch status with retry"""
645
646
        # Set a side effect on the patched methods
647
        # so that they raise the errors we want.
648
        my_retry.side_effect = Retry()
649
        my_fetch.side_effect = USIConnectionError()
650
651
        with raises(Retry):
652
            self.my_task.run()
653
654
        self.assertTrue(my_fetch.called)
655
        self.assertTrue(my_retry.called)
656
657
        # assert no helper called for this submission
658
        self.assertFalse(self.mock_helper.called)
659
        self.assertFalse(self.mock_complete.called)
660
661
    # Test a non blocking instance
662
    @patch("biosample.tasks.FetchStatusTask.fetch_queryset")
663
    @patch("redis.lock.Lock.acquire", return_value=False)
664
    def test_fetch_status_nb(self, my_lock, my_fetch):
665
        """Test FetchSTatus while a lock is present"""
666
667
        res = self.my_task.run()
668
669
        # assert database is locked
670
        self.assertEqual(res, "%s already running!" % (self.my_task.name))
671
        self.assertFalse(my_fetch.called)
672
673
        # assert no helper called for this submission
674
        self.assertFalse(self.mock_helper.called)
675
        self.assertFalse(self.mock_complete.called)
676
677
678
class RetrievalCompleteTaskTestCase(FetchMixin, WebSocketMixin, TestCase):
679
    """testing update status after a fetch status"""
680
681
    def setUp(self):
682
        # calling my base setup
683
        super().setUp()
684
685
        # set proper status to biosample.models.Submission
686
        USISubmission.objects.update(status=SUBMITTED)
687
688
        # define my task
689
        self.my_task = RetrievalCompleteTask()
690
691
    def updated_check(self, status, message, validation_message=None):
692
        """Common check for tests"""
693
694
        # set proper status to biosample.models.Submission
695
        USISubmission.objects.update(status=status, message=message)
696
697
        # calling task
698
        result = self.my_task.run(
699
            uid_submission_id=self.submission_obj_id)
700
701
        # assert a success with data uploading
702
        self.assertEqual(result, "success")
703
704
        # check status and messages
705
        self.submission_obj.refresh_from_db()
706
        self.assertEqual(self.submission_obj.status, status)
707
        self.assertEqual(self.submission_obj.message, message)
708
709
        # calling a WebSocketMixin method
710
        self.check_message(
711
            STATUSES.get_value_display(status),
712
            message,
713
            validation_message)
714
715
    def not_updated_check(self, status, message):
716
        """Test a submission not updated"""
717
718
        # set proper status to biosample.models.Submission
719
        USISubmission.objects.filter(pk=1).update(
720
            status=status, message=message)
721
722
        # calling task
723
        result = self.my_task.run(
724
            uid_submission_id=self.submission_obj_id)
725
726
        # assert a success with data uploading
727
        self.assertEqual(result, "success")
728
729
        # check status and messages
730
        self.submission_obj.refresh_from_db()
731
        self.assertEqual(self.submission_obj.status, SUBMITTED)
732
        self.assertEqual(
733
            self.submission_obj.message,
734
            "Waiting for biosample validation")
735
736
        # defined in websoketmixin
737
        self.check_message_not_called()
738
739
    def test_submitted(self):
740
        """Test submitted status"""
741
742
        status = SUBMITTED
743
        message = "Waiting for biosample validation"
744
745
        self.not_updated_check(
746
            status,
747
            message)
748
749
    def issues_with_usi(self):
750
        """Change database and set stuff to simulate issues with USI"""
751
752
        # before doing tests, update validationresult
753
        result = ValidationResult.objects.get(pk=1)
754
        result.status = "Error"
755
        result.messages = ["message1", "message2"]
756
        result.save()
757
758
        # also summary changes with the same conditions
759
        summary = ValidationSummary.objects.get(pk=1)
760
        summary.pass_count = F('pass_count') - 1
761
        summary.error_count = F('error_count') + 1
762
        summary.issues_count = F('issues_count') + 1
763
        summary.save()
764
765
        validation_message = {
766
            'animals': 3, 'samples': 1, 'animal_unkn': 0,
767
            'sample_unkn': 0, 'animal_issues': 1, 'sample_issues': 0}
768
769
        summary_message = [
770
            {'ids': [1],
771
             'count': 1,
772
             'message': 'message1',
773
             'offending_column': ''},
774
            {'ids': [1],
775
             'count': 1,
776
             'message': 'message2',
777
             'offending_column': ''}]
778
779
        # returning custom values
780
        return validation_message, summary_message
781
782
    def test_error(self):
783
        """test an error in a submission"""
784
785
        # prepare database for issues with USI
786
        validation_message, summary_message = self.issues_with_usi()
787
788
        status = ERROR
789
        message = "error messages"
790
791
        self.updated_check(
792
            status,
793
            message,
794
            validation_message)
795
796
        # test email sent
797
        self.assertEqual(len(mail.outbox), 1)
798
799
        # read email
800
        email = mail.outbox[0]
801
802
        self.assertEqual(
803
            "Error in biosample submission 1",
804
            email.subject)
805
806
        # ok get validationsummary object
807
        summary = ValidationSummary.objects.get(
808
            submission=self.submission_obj,
809
            type="animal")
810
811
        self.assertListEqual(summary.messages, summary_message)
812
813
    def test_need_revision(self):
814
        """test an issue in a submission"""
815
816
        # prepare database for issues with USI
817
        validation_message, summary_message = self.issues_with_usi()
818
819
        status = NEED_REVISION
820
        message = "error messages"
821
822
        self.updated_check(
823
            status,
824
            message,
825
            validation_message)
826
827
        # test email sent
828
        self.assertEqual(len(mail.outbox), 1)
829
830
        # read email
831
        email = mail.outbox[0]
832
833
        self.assertEqual(
834
            "Error in biosample submission 1",
835
            email.subject)
836
837
        # ok get validationsummary object
838
        summary = ValidationSummary.objects.get(
839
            submission=self.submission_obj,
840
            type="animal")
841
842
        self.assertListEqual(summary.messages, summary_message)
843
844
    def test_completed(self):
845
        """test a submission completed"""
846
847
        status = COMPLETED
848
        message = "completed messages"
849
850
        validation_message = {
851
            'animals': 3, 'samples': 1, 'animal_unkn': 0,
852
            'sample_unkn': 0, 'animal_issues': 0, 'sample_issues': 0}
853
854
        self.updated_check(
855
            status,
856
            message,
857
            validation_message)
858
859
    def test_partial_submitted(self):
860
        """Having submitted in statuses will not complete the submission"""
861
862
        status = ERROR
863
        message = "error messages"
864
865
        self.not_updated_check(
866
            status,
867
            message)
868
869
        status = NEED_REVISION
870
        message = "error messages"
871
872
        self.not_updated_check(
873
            status,
874
            message)
875
876
        status = COMPLETED
877
        message = "completed messages"
878
879
        self.not_updated_check(
880
            status,
881
            message)
882