コード例 #1
0
    def test_detail_response(self, app, user, user_two):
        draft_reg = DraftRegistrationFactory(initiator=user)
        draft_reg.add_contributor(user_two)
        draft_reg.save()

        draft_node = draft_reg.branched_from

        # Unauthenticated
        url = '/{}draft_nodes/{}/'.format(API_BASE, draft_node._id)
        res = app.get(url, expect_errors=True)
        assert res.status_code == 401

        # Draft Node and Draft Registration contributor
        res = app.get(url, auth=user.auth)
        assert res.status_code == 200

        # Draft Registration contributor only
        res = app.get(url, auth=user_two.auth)
        assert res.status_code == 200
        data = res.json['data']

        assert data['attributes'] == {}
        assert data['type'] == 'draft-nodes'
        assert data['id'] == draft_node._id

        assert url + 'files/' in data['relationships']['files']['links'][
            'related']['href']
        assert url in data['links']['self']

        # assert cannot access node through this endpoint
        project = ProjectFactory(creator=user)
        url = '/{}draft_nodes/{}/'.format(API_BASE, project._id)
        res = app.get(url, expect_errors=True)
        assert res.status_code == 404

        # cannot access draft node after it's been registered (it's now a node!)
        draft_reg.register(Auth(user))
        url = '/{}draft_nodes/{}/'.format(API_BASE, draft_node._id)
        res = app.get(url, auth=user_two.auth, expect_errors=True)
        assert res.status_code == 404
コード例 #2
0
class TestRegistrationCreate(DraftRegistrationTestCase):
    def setUp(self):
        super(TestRegistrationCreate, self).setUp()

        self.schema = MetaSchema.find_one(
            Q('name', 'eq', 'Replication Recipe (Brandt et al., 2013): Post-Completion') &
            Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)
        )

        self.draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=self.public_project,
            registration_metadata = {
                'item29': {'value': 'Yes'},
                'item33': {'value': 'success'}
            }
        )

        self.url = '/{}nodes/{}/registrations/'.format(API_BASE, self.public_project._id)

        self.payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "immediate"
                    }
                }
        }

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_admin_can_create_registration(self, mock_enqueue):
        res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth)
        data = res.json['data']['attributes']
        assert_equal(res.status_code, 201)
        assert_equal(data['registration'], True)
        assert_equal(data['pending_registration_approval'], True)
        assert_equal(data['public'], False)

    def test_write_only_contributor_cannot_create_registration(self):
        res = self.app.post_json_api(self.url, self.payload, auth=self.read_write_user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_read_only_contributor_cannot_create_registration(self):
        res = self.app.post_json_api(self.url, self.payload, auth=self.read_only_user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_non_authenticated_user_cannot_create_registration(self):
        res = self.app.post_json_api(self.url, self.payload, expect_errors=True)
        assert_equal(res.status_code, 401)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_specified(self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate"
                    }
                }
        }
        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/attributes/draft_registration')
        assert_equal(res.json['errors'][0]['detail'], 'This field is required.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_valid(self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": "12345"
                    }
                }
        }
        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_draft_of_current_node(self, mock_enqueue):
        new_project = ProjectFactory(creator=self.user)
        draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=new_project,
            registration_metadata = {
                'item29': {'value': 'Yes'},
                'item33': {'value': 'success'}
            }
        )
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": draft_registration._id
                    }
                }
        }
        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This draft registration is not created from the given node.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_top_level_questions_must_be_answered_on_draft(self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge') &
            Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)
        )

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project
        )

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        del registration_metadata['q1']
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "u'q1' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_top_level_questions_must_be_answered_on_draft(self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge') &
            Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)
        )

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project
        )

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        del registration_metadata['q1']
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "u'q1' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_second_level_questions_must_be_answered_on_draft(self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge') &
            Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)
        )

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project
        )

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        registration_metadata['q11'] = {'value': {}}
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "u'question' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_third_level_questions_must_be_answered_on_draft(self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge') &
            Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)
        )

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project
        )

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        registration_metadata['q11'] = {'value': {"question": {}}}

        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "'value' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_multiple_choice_in_registration_schema_must_match_one_of_choices(self, mock_enqueue):
        draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=self.public_project,
            registration_metadata = {
                'item29': {'value': 'Yes'},
                'item33': {'value': 'success!'}
            }
        )
        self.payload['data']['attributes']['draft_registration'] = draft_registration._id
        res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "u'success!' is not one of [u'success', u'informative failure to replicate',"
                                                      " u'practical failure to replicate', u'inconclusive']")

    def test_invalid_registration_choice(self):
        self.payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "tomorrow"
                    }
                }
        }
        res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/attributes/registration_choice')
        assert_equal(res.json['errors'][0]['detail'], '"tomorrow" is not a valid choice.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_end_date_provided_if_registration_choice_is_embargo(self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo"
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'lift_embargo must be specified.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_must_be_less_than_four_years(self, mock_enqueue):
        today = timezone.now()
        five_years = (today + dateutil.relativedelta.relativedelta(years=5)).strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": five_years
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Registrations can only be embargoed for up to four years.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_registration(self, mock_enqueue):
        today = timezone.now()
        next_week = (today + dateutil.relativedelta.relativedelta(months=1)).strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": next_week
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 201)
        data = res.json['data']['attributes']
        assert_equal(data['registration'], True)
        assert_equal(data['pending_embargo_approval'], True)

    def test_embargo_end_date_must_be_in_the_future(self):
        today = timezone.now().strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": today
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Embargo end date must be at least three days in the future.')

    def test_invalid_embargo_end_date_format(self):
        today = timezone.now().isoformat()
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": today
                    }
                }
        }

        res = self.app.post_json_api(self.url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm:ss.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_cannot_register_draft_that_has_already_been_registered(self, mock_enqueue):
        self.draft_registration.register(auth=Auth(self.user), save=True)
        res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'], 'This draft has already been registered and cannot be modified.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_cannot_register_draft_that_is_pending_review(self, mock_enqueue):
        with mock.patch.object(DraftRegistration, 'is_pending_review', mock.PropertyMock(return_value=True)):
            res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'], 'This draft is pending review and cannot be modified.')

    def test_cannot_register_draft_that_has_already_been_approved(self):
        with mock.patch.object(DraftRegistration, 'requires_approval', mock.PropertyMock(return_value=True)), mock.patch.object(DraftRegistration, 'is_approved', mock.PropertyMock(return_value=True)):
            res = self.app.post_json_api(self.url, self.payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'], 'This draft has already been approved and cannot be modified.')
コード例 #3
0
class TestDraftListView(AdminTestCase):
    @mock.patch('website.archiver.tasks.archive')
    def setUp(self, mock_archive):
        super(TestDraftListView, self).setUp()
        self.user = AuthUserFactory()
        self.schema = utils.draft_reg_util()
        self.dr1 = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA)
        self.dr1.submit_for_review(self.user, {}, save=True)
        self.dr2 = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA)
        self.dr2.submit_for_review(self.user, {}, save=True)
        # Simply here to NOT be returned when get_queryset is called
        self.unsubmitted_prereg = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA)
        self.unsubmitted_prereg.register(Auth(self.user), save=True)
        self.request = RequestFactory().get('/fake_path')
        self.plain_view = DraftListView
        self.view = setup_view(self.plain_view(), self.request)

        self.url = reverse('pre_reg:prereg')

    def test_get_queryset(self):
        res = list(self.view.get_queryset())
        nt.assert_equal(len(res), 2)
        nt.assert_false(self.unsubmitted_prereg in res)
        nt.assert_is_instance(res[0], DraftRegistration)

    def test_queryset_returns_in_order_date_submitted(self):
        created_first_submitted_second = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA)

        created_second_submitted_first = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA)

        nt.assert_greater(created_second_submitted_first.datetime_initiated,
                          created_first_submitted_second.datetime_initiated)

        created_second_submitted_first.submit_for_review(self.user, {},
                                                         save=True)
        created_first_submitted_second.submit_for_review(self.user, {},
                                                         save=True)
        created_second_submitted_first.datetime_updated = created_first_submitted_second.datetime_updated + datetime.timedelta(
            1)

        assert created_second_submitted_first.datetime_updated > created_first_submitted_second.datetime_updated
        res = list(self.view.get_queryset())
        nt.assert_true(res[0] == created_first_submitted_second)

    def test_get_context_data(self):
        self.view.object_list = self.view.get_queryset()
        res = self.view.get_context_data()
        nt.assert_is_instance(res, dict)
        nt.assert_is_instance(res['drafts'], list)
        nt.assert_equal(len(res['drafts']), 2)

    def test_no_user_permissions_raises_error(self):
        request = RequestFactory().get(self.url)
        request.user = self.user

        with nt.assert_raises(PermissionDenied):
            self.plain_view.as_view()(request)

    def test_correct_view_permissions(self):
        view_permission = Permission.objects.get(codename='view_prereg')
        self.user.user_permissions.add(view_permission)
        self.user.save()

        request = RequestFactory().get(self.url)
        request.user = self.user

        response = self.plain_view.as_view()(request)
        nt.assert_equal(response.status_code, 200)
コード例 #4
0
ファイル: test_views.py プロジェクト: erinspace/osf.io
class TestDraftListView(AdminTestCase):
    @mock.patch('website.archiver.tasks.archive')
    def setUp(self, mock_archive):
        super(TestDraftListView, self).setUp()
        self.user = AuthUserFactory()
        self.schema = utils.draft_reg_util()
        self.dr1 = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA
        )
        self.dr1.submit_for_review(self.user, {}, save=True)
        self.dr2 = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA
        )
        self.dr2.submit_for_review(self.user, {}, save=True)
        # Simply here to NOT be returned when get_queryset is called
        self.unsubmitted_prereg = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA
        )
        self.unsubmitted_prereg.register(Auth(self.user), save=True)
        self.request = RequestFactory().get('/fake_path')
        self.plain_view = DraftListView
        self.view = setup_view(self.plain_view(), self.request)

        self.url = reverse('pre_reg:prereg')

    def test_get_queryset(self):
        res = list(self.view.get_queryset())
        nt.assert_equal(len(res), 2)
        nt.assert_false(self.unsubmitted_prereg in res)
        nt.assert_is_instance(res[0], DraftRegistration)

    def test_queryset_returns_in_order_date_submitted(self):
        created_first_submitted_second = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA
        )

        created_second_submitted_first = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            registration_metadata=utils.SCHEMA_DATA
        )

        nt.assert_greater(created_second_submitted_first.datetime_initiated, created_first_submitted_second.datetime_initiated)

        created_second_submitted_first.submit_for_review(self.user, {}, save=True)
        created_first_submitted_second.submit_for_review(self.user, {}, save=True)
        created_second_submitted_first.datetime_updated = created_first_submitted_second.datetime_updated + datetime.timedelta(1)

        assert created_second_submitted_first.datetime_updated > created_first_submitted_second.datetime_updated
        res = list(self.view.get_queryset())
        nt.assert_true(res[0] == created_first_submitted_second)

    def test_get_context_data(self):
        self.view.object_list = self.view.get_queryset()
        res = self.view.get_context_data()
        nt.assert_is_instance(res, dict)
        nt.assert_is_instance(res['drafts'], list)
        nt.assert_equal(len(res['drafts']), 2)

    def test_no_user_permissions_raises_error(self):
        request = RequestFactory().get(self.url)
        request.user = self.user

        with nt.assert_raises(PermissionDenied):
            self.plain_view.as_view()(request)

    def test_correct_view_permissions(self):
        view_permission = Permission.objects.get(codename='view_prereg')
        self.user.user_permissions.add(view_permission)
        self.user.save()

        request = RequestFactory().get(self.url)
        request.user = self.user

        response = self.plain_view.as_view()(request)
        nt.assert_equal(response.status_code, 200)
コード例 #5
0
class TestRegistrationCreate(DraftRegistrationTestCase):
    def setUp(self):
        super(TestRegistrationCreate, self).setUp()
        ensure_schemas()

        self.schema = MetaSchema.find_one(
            Q('name', 'eq',
              'Replication Recipe (Brandt et al., 2013): Post-Completion')
            & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION))

        self.draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=self.public_project,
            registration_metadata={
                'item29': {
                    'value': 'Yes'
                },
                'item33': {
                    'value': 'success'
                }
            })

        self.url = '/{}nodes/{}/registrations/'.format(API_BASE,
                                                       self.public_project._id)

        self.payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "immediate"
                }
            }
        }

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_admin_can_create_registration(self, mock_enqueue):
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.user.auth)
        data = res.json['data']['attributes']
        assert_equal(res.status_code, 201)
        assert_equal(data['registration'], True)
        assert_equal(data['pending_registration_approval'], True)
        assert_equal(data['public'], False)

    def test_write_only_contributor_cannot_create_registration(self):
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.read_write_user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_read_only_contributor_cannot_create_registration(self):
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.read_only_user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_non_authenticated_user_cannot_create_registration(self):
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     expect_errors=True)
        assert_equal(res.status_code, 401)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_specified(self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate"
                }
            }
        }
        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'],
                     '/data/attributes/draft_registration')
        assert_equal(res.json['errors'][0]['detail'],
                     'This field is required.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_valid(self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": "12345"
                }
            }
        }
        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 404)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_registration_draft_must_be_draft_of_current_node(
            self, mock_enqueue):
        new_project = ProjectFactory(creator=self.user)
        draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=new_project,
            registration_metadata={
                'item29': {
                    'value': 'Yes'
                },
                'item33': {
                    'value': 'success'
                }
            })
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": draft_registration._id
                }
            }
        }
        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This draft registration is not created from the given node.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_top_level_questions_must_be_answered_on_draft(
            self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge')
            & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION))

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project)

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        del registration_metadata['q1']
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     "u'q1' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_top_level_questions_must_be_answered_on_draft(
            self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge')
            & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION))

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project)

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        del registration_metadata['q1']
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     "u'q1' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_second_level_questions_must_be_answered_on_draft(
            self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge')
            & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION))

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project)

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        registration_metadata['q11'] = {'value': {}}
        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     "u'question' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_required_third_level_questions_must_be_answered_on_draft(
            self, mock_enqueue):
        prereg_schema = MetaSchema.find_one(
            Q('name', 'eq', 'Prereg Challenge')
            & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION))

        prereg_draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=prereg_schema,
            branched_from=self.public_project)

        registration_metadata = self.prereg_metadata(prereg_draft_registration)
        registration_metadata['q11'] = {'value': {"question": {}}}

        prereg_draft_registration.registration_metadata = registration_metadata
        prereg_draft_registration.save()

        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "registration_choice": "immediate",
                    "draft_registration": prereg_draft_registration._id,
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     "'value' is a required property")

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_multiple_choice_in_registration_schema_must_match_one_of_choices(
            self, mock_enqueue):
        draft_registration = DraftRegistrationFactory(
            initiator=self.user,
            registration_schema=self.schema,
            branched_from=self.public_project,
            registration_metadata={
                'item29': {
                    'value': 'Yes'
                },
                'item33': {
                    'value': 'success!'
                }
            })
        self.payload['data']['attributes'][
            'draft_registration'] = draft_registration._id
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            "u'success!' is not one of [u'success', u'informative failure to replicate',"
            " u'practical failure to replicate', u'inconclusive']")

    def test_invalid_registration_choice(self):
        self.payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "tomorrow"
                }
            }
        }
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'],
                     '/data/attributes/registration_choice')
        assert_equal(res.json['errors'][0]['detail'],
                     '"tomorrow" is not a valid choice.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_end_date_provided_if_registration_choice_is_embargo(
            self, mock_enqueue):
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo"
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'lift_embargo must be specified.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_must_be_less_than_four_years(self, mock_enqueue):
        today = timezone.now()
        five_years = (today + dateutil.relativedelta.relativedelta(years=5)
                      ).strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": five_years
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'Registrations can only be embargoed for up to four years.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_embargo_registration(self, mock_enqueue):
        today = timezone.now()
        next_week = (today + dateutil.relativedelta.relativedelta(months=1)
                     ).strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": next_week
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 201)
        data = res.json['data']['attributes']
        assert_equal(data['registration'], True)
        assert_equal(data['pending_embargo_approval'], True)

    def test_embargo_end_date_must_be_in_the_future(self):
        today = timezone.now().strftime('%Y-%m-%dT%H:%M:%S')
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": today
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'Embargo end date must be at least three days in the future.')

    def test_invalid_embargo_end_date_format(self):
        today = timezone.now().isoformat()
        payload = {
            "data": {
                "type": "registrations",
                "attributes": {
                    "draft_registration": self.draft_registration._id,
                    "registration_choice": "embargo",
                    "lift_embargo": today
                }
            }
        }

        res = self.app.post_json_api(self.url,
                                     payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm:ss.'
        )

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_cannot_register_draft_that_has_already_been_registered(
            self, mock_enqueue):
        self.draft_registration.register(auth=Auth(self.user), save=True)
        res = self.app.post_json_api(self.url,
                                     self.payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This draft has already been registered and cannot be modified.')

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_cannot_register_draft_that_is_pending_review(self, mock_enqueue):
        with mock.patch.object(DraftRegistration, 'is_pending_review',
                               mock.PropertyMock(return_value=True)):
            res = self.app.post_json_api(self.url,
                                         self.payload,
                                         auth=self.user.auth,
                                         expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'This draft is pending review and cannot be modified.')

    def test_cannot_register_draft_that_has_already_been_approved(self):
        with mock.patch.object(
                DraftRegistration, 'requires_approval',
                mock.PropertyMock(return_value=True)), mock.patch.object(
                    DraftRegistration, 'is_approved',
                    mock.PropertyMock(return_value=True)):
            res = self.app.post_json_api(self.url,
                                         self.payload,
                                         auth=self.user.auth,
                                         expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This draft has already been approved and cannot be modified.')