Completed
Pull Request — master (#93)
by Paolo
08:39 queued 06:50
created

FetchMixin.tearDownClass()   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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