Exemple #1
0
    def test_by_ids(self, req, dbsession,):
        """
        It should allow search via direct ids (for pre-entered values)
        """
        from datetime import date
        from occams import models
        from webob.multidict import MultiDict

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(name='week-1', title=u'Foo Week 1', week=1)
        cycle2 = models.Cycle(name='week-2', title=u'Bar Week 2', week=2)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        study.cycles.append(cycle1)
        study.cycles.append(cycle2)

        dbsession.add_all([patient, study])
        dbsession.flush()

        req.GET = MultiDict([('ids', cycle1.id)])
        res = self._call_fut(patient['visits'], req)

        assert cycle1.id == res['cycles'][0]['id']
Exemple #2
0
    def test_call_success(self, req, dbsession,):
        """
        It should be able to validate cycles via GET (for AJAX req)
        """
        from datetime import date
        from occams import models
        from webob.multidict import MultiDict

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(name='week-1', title=u'Foo Week 1', week=1)
        cycle2 = models.Cycle(name='week-2', title=u'Bar Week 2', week=2)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        study.cycles.append(cycle1)
        study.cycles.append(cycle2)

        dbsession.add_all([patient, study])
        dbsession.flush()

        req.GET = MultiDict([
            ('cycles', ','.join(map(str, [cycle1.id, cycle2.id])))])

        res = self._call_fut(patient['visits'], req)

        assert res
Exemple #3
0
    def test_update_cycles(self, req, dbsession, check_csrf_token):
        """
        It should also update cycle versions
        """
        from datetime import date, timedelta
        from occams import models as datastore
        from occams import models

        today = date.today()
        tomorrow = today + timedelta(days=1)

        v1 = datastore.Schema(name=u'test', title=u'', publish_date=today)
        v2 = datastore.Schema(name=u'test', title=u'', publish_date=tomorrow)

        cycle = models.Cycle(name=u'wk-001',
                             title=u'WK-001',
                             schemata=set([v1]))

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             cycles=[cycle],
                             schemata=set([v1]),
                             consent_date=date.today())

        dbsession.add_all([study, v1, v2])
        dbsession.flush()

        req.json_body = {'schema': v1.name, 'versions': [v2.id]}
        self._call_fut(study, req)

        assert v2 in study.schemata
        # v2 should have been passed on to the cycle using it as well
        assert v2 in cycle.schemata
Exemple #4
0
    def test_success(self, req, dbsession, check_csrf_token):
        """
        It should remove the schema from the study and cascade to its cycles
        """
        from datetime import date
        from occams import models as datastore
        from occams import models

        schema = datastore.Schema(name='test',
                                  title=u'',
                                  publish_date=date.today())

        cycle = models.Cycle(name='week-1',
                             title=u'Week 1',
                             week=1,
                             schemata=set([schema]))

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle],
                             schemata=set([schema]))

        dbsession.add_all([study, schema])
        dbsession.flush()

        req.matchdict = {'schema': schema.name}
        self._call_fut(study, req)

        assert schema not in study.schemata
        assert schema not in cycle.schemata
Exemple #5
0
    def test_edit_unique_name(self, req, dbsession):
        """
        It should allow the cycle to be able to change its unique name
        """
        from datetime import date
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'Week 1', week=1)

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle])

        dbsession.add_all([study])
        dbsession.flush()

        req.json_body = {
            'name': 'somestudy',
            'title': cycle.title,
            'week': cycle.week
        }

        res = self._call_fut(cycle, req)
        assert res is not None
Exemple #6
0
    def test_enforce_unique_name(self, req, dbsession):
        """
        It should make sure the name stays unique when adding new cycles
        """
        from datetime import date
        from pyramid.httpexceptions import HTTPBadRequest
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'Week 1', week=1)

        study = models.Study(name=u'some-study',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle])

        dbsession.add_all([study])
        dbsession.flush()

        req.json_body = {'title': u'Week 1', 'week': 2}

        with pytest.raises(HTTPBadRequest) as excinfo:
            self._call_fut(study['cycles'], req)

        assert 'not yield a unique' in \
            excinfo.value.json['errors']['title'].lower()
Exemple #7
0
    def test_update_patient(self, req, dbsession, check_csrf_token):
        """
        It should also mark the patient as modified
        """
        from datetime import date
        from occams import models

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(study=study, name='week-1', title=u'', week=1)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        dbsession.add_all([patient, study])
        dbsession.flush()

        old_modify_date = patient.modify_date

        req.json_body = {
            'cycles': [str(cycle1.id)],
            'visit_date': str(date.today())
        }

        self._call_fut(patient['visits'], req)

        assert old_modify_date < patient.modify_date
Exemple #8
0
    def test_enable(self, req, dbsession, check_csrf_token):
        """
        It should successfully add a schema to a cycle
        """
        from datetime import date
        from occams import models as datastore
        from occams import models

        schema = datastore.Schema(name='test',
                                  title=u'Test',
                                  publish_date=date.today())

        cycle = models.Cycle(name='week-1', title=u'Week 1', week=1)

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle],
                             schemata=set([schema]))

        dbsession.add_all([study, schema])
        dbsession.flush()

        req.json_body = {
            'schema': schema.name,
            'cycle': cycle.id,
            'enabled': True
        }

        self._call_fut(study, req)

        assert schema in cycle.schemata
Exemple #9
0
    def test_unique_visit_date(self, req, dbsession, check_csrf_token):
        """
        It should not allow duplicate visit dates
        """
        from datetime import date
        from pyramid.httpexceptions import HTTPBadRequest
        from occams import models

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(name='week-1', title=u'', week=1)
        cycle2 = models.Cycle(name='week-2', title=u'', week=2)

        study.cycles.append(cycle1)
        study.cycles.append(cycle2)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        visit = models.Visit(
            patient=patient,
            cycles=[cycle1],
            visit_date=date.today())

        dbsession.add_all([patient, study, visit])
        dbsession.flush()

        req.json_body = {
            'cycles': [cycle2.id],
            'visit_date': str(date.today())
        }

        # Update the visit, should allow to update the date
        self._call_fut(visit, req)

        # New visits cannot share dates
        with pytest.raises(HTTPBadRequest) as excinfo:
            self._call_fut(patient['visits'], req)

        assert 'already exists' in \
            excinfo.value.json['errors']['visit_date']
Exemple #10
0
    def test_success(self, req, dbsession, check_csrf_token):
        """
        It should allow removal of entities from a visit.
        """
        from datetime import date, timedelta
        from pyramid.httpexceptions import HTTPOk
        from occams import models as datastore
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'', week=1)

        schema = datastore.Schema(
            name=u'sample', title=u'', publish_date=date.today())

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today(),
            cycles=[cycle],
            schemata=set([schema]))

        site = models.Site(name=u'ucsd', title=u'UCSD')

        default_state = (
            dbsession.query(datastore.State)
            .filter_by(name=u'pending-entry')
            .one())

        t_a = date.today() + timedelta(days=5)
        patient_a = models.Patient(site=site, pid=u'12345')
        visit_a = models.Visit(
            patient=patient_a, cycles=[cycle], visit_date=t_a)
        entity_a_1 = datastore.Entity(
            schema=schema, collect_date=t_a, state=default_state)
        entity_a_2 = datastore.Entity(
            schema=schema, collect_date=t_a, state=default_state)
        entity_a_3 = datastore.Entity(
            schema=schema, collect_date=t_a, state=default_state)
        list(map(visit_a.entities.add, [entity_a_1, entity_a_2, entity_a_3]))

        dbsession.add_all([visit_a, study])
        dbsession.flush()

        req.json_body = {
            'forms': [entity_a_2.id, entity_a_3.id]
        }

        res = self._call_fut(visit_a['forms'], req)

        # refresh the session so we can get a correct listing
        dbsession.expunge_all()
        visit_a = dbsession.query(models.Visit).get(visit_a.id)

        assert isinstance(res, HTTPOk)
        assert sorted([e.id for e in [entity_a_1]]) == \
            sorted([e.id for e in visit_a.entities])
Exemple #11
0
    def test_cascade_forms(self, req, dbsession, check_csrf_token):
        """
        It should remove all visit-associated forms.
        """
        from datetime import date
        from occams import models as datastore
        from occams import models

        schema = datastore.Schema(
            name=u'sample',
            title=u'Some Sample',
            publish_date=date.today())

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle = models.Cycle(
            name=u'week-10',
            title=u'Week 10',
            week=10)

        study.cycles.append(cycle)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        enrollment = models.Enrollment(
            study=study,
            patient=patient,
            consent_date=date.today())

        visit = models.Visit(
            patient=patient,
            cycles=[cycle],
            visit_date=date.today())

        visit.entities.add(datastore.Entity(
            schema=schema,
            collect_date=date.today()))

        dbsession.add_all([patient, enrollment, study, visit])
        dbsession.flush()

        visit_id = visit.id

        self._call_fut(visit, req)

        assert dbsession.query(models.Visit).get(visit_id) is None
        assert 0 == dbsession.query(datastore.Entity).count()
Exemple #12
0
    def populate(self, app, dbsession):
        import transaction
        from occams import models
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = models.User(key=USERID)
            dbsession.info['blame'] = user
            dbsession.add(user)
            dbsession.flush()

            site = models.Site(name=u'UCSD',
                               title=u'UCSD',
                               description=u'UCSD Campus',
                               create_date=date.today())

            patient = models.Patient(initials=u'ian',
                                     nurse=u'*****@*****.**',
                                     site=site,
                                     pid=u'123')

            form = models.Schema(name=u'test_schema',
                                 title=u'test_title',
                                 publish_date=date(2015, 1, 1))

            study = models.Study(name=u'test_study',
                                 code=u'test_code',
                                 consent_date=date(2014, 12, 23),
                                 is_randomized=False,
                                 title=u'test_title',
                                 short_title=u'test_short',
                                 schemata=set([form]))

            cycle = models.Cycle(name=u'TestCycle',
                                 title=u'TestCycle',
                                 week=39,
                                 study=study)

            visit = models.Visit(patient=patient,
                                 cycles=[cycle],
                                 visit_date='2015-01-01')

            entity = models.Entity(schema=form, collect_date=date(2015, 1, 1))

            dbsession.add(study)
            dbsession.add(patient)
            dbsession.add(visit)
            dbsession.add(entity)
            patient.entities.add(entity)
Exemple #13
0
    def populate(self, app, dbsession):

        import transaction
        from occams import models
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = models.User(key=USERID)
            dbsession.info['blame'] = user
            dbsession.add(user)
            dbsession.flush()

            site = models.Site(
                name=u'UCSD',
                title=u'UCSD',
                description=u'UCSD Campus',
                create_date=date.today())

            patient = models.Patient(
                initials=u'ian',
                nurse=u'*****@*****.**',
                site=site,
                pid=u'123'
            )

            study = models.Study(
                name=u'test_study',
                code=u'test_code',
                consent_date=date(2014, 12, 23),
                is_randomized=False,
                title=u'test_title',
                short_title=u'test_short',
            )

            cycle = models.Cycle(
                name=u'TestView',
                title=u'TestView',
                week=39,
                study=study
            )

            dbsession.add(study)
            dbsession.add(patient)
            dbsession.add(cycle)
Exemple #14
0
    def test_unique_cycle(self, req, dbsession, check_csrf_token):
        """
        It should not allow repeat cycles (unless it's interim)
        """
        from datetime import date, timedelta
        from pyramid.httpexceptions import HTTPBadRequest
        from occams import models

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle = models.Cycle(name='week-1', title=u'', week=1)

        study.cycles.append(cycle)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        visit = models.Visit(
            patient=patient, cycles=[cycle], visit_date=date.today())

        dbsession.add_all([patient, study, visit])
        dbsession.flush()

        req.json_body = {
            'cycles': [cycle.id],
            'visit_date': str(date.today() + timedelta(days=1))
        }

        with pytest.raises(HTTPBadRequest) as excinfo:
            self._call_fut(patient['visits'], req)

        assert 'already in use' in \
            excinfo.value.json['errors']['cycles-0'].lower()

        # The exception is interims
        cycle.is_interim = True
        dbsession.flush()
        res = self._call_fut(patient['visits'], req)

        assert res is not None
Exemple #15
0
    def test_include_not_retracted_form(
            self, req, dbsession, check_csrf_token):
        """
        It should not use retracted forms, even if there are the most recent
        """
        from datetime import date, timedelta
        from occams import models as datastore
        from occams import models

        t0 = date.today()
        t1 = t0 + timedelta(days=1)
        t2 = t1 + timedelta(days=1)

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(name='week-1', title=u'', week=1)
        cycle1.schemata.update([
            datastore.Schema(name='form1', title=u'', publish_date=t0),
            datastore.Schema(name='form1', title=u'', publish_date=t2,
                             retract_date=t2)])
        study.cycles.append(cycle1)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        dbsession.add_all([patient, study])
        dbsession.flush()

        req.json_body = {
            'cycles': [cycle1.id],
            'visit_date': str(t2),
            'include_forms': True
        }

        res = self._call_fut(patient['visits'], req)

        assert 1 == len(res['entities'])
        assert str(t0) == res['entities'][0]['schema']['publish_date']
Exemple #16
0
    def test_cycle_in_study(self, req, dbsession, check_csrf_token):
        """
        It should fail if the cycle is not part of the study
        """
        from datetime import date
        from pyramid.httpexceptions import HTTPBadRequest
        from occams import models as datastore
        from occams import models

        schema = datastore.Schema(name='test',
                                  title=u'Test',
                                  publish_date=date.today())

        other_cycle = models.Cycle(name=u'week-1', title=u'Title', week=1)

        other_study = models.Study(name=u'otherstudy',
                                   title=u'Other Study',
                                   short_title=u'ostudy',
                                   code=u'111',
                                   consent_date=date.today(),
                                   cycles=[other_cycle])

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             schemata=set([schema]))

        dbsession.add_all([study, schema, other_study])
        dbsession.flush()

        req.json_body = {
            'schema': schema.name,
            'cycle': other_cycle.id,
            'enabled': True
        }

        with pytest.raises(HTTPBadRequest) as excinfo:
            self._call_fut(study, req)

        assert 'not a valid choice' in \
            excinfo.value.json['errors']['cycle'].lower()
Exemple #17
0
    def test_add_to_visit(self, req, dbsession):
        from datetime import date
        from occams import models

        schema = models.Schema(name=u'schema',
                               title=u'Schema',
                               publish_date=date.today())

        study = models.Study(name='some-study',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             schemata=set([schema]))

        cycle = models.Cycle(study=study, name=u'cycle-1', title=u'Cycle')

        site = models.Site(name=u'somewhere', title=u'Somewhere')
        patient = models.Patient(pid=u'12345', site=site)

        visit = models.Visit(patient=patient,
                             visit_date=date.today(),
                             cycles=[cycle])

        dbsession.add_all([study, patient, visit])
        dbsession.flush()

        req.matchdict = {'patient': patient, 'visit': visit}
        req.json_body = {
            'schema': schema.id,
            'collect_date': str(date.today()),
        }
        factory = models.FormFactory(req)
        factory.__parent__ = visit
        self._call_fut(factory, req)

        contexts = dbsession.query(models.Context).all()

        assert len(contexts) == 2
        assert sorted(['patient', 'visit']) == \
            sorted([c.external for c in contexts])
Exemple #18
0
    def test_not_in_study(self, req, dbsession):
        """
        It should fail if the form is not part of the study
        """
        from datetime import date, timedelta
        from pyramid.httpexceptions import HTTPBadRequest
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'', week=1)

        schema = models.Schema(name=u'sample',
                               title=u'',
                               publish_date=date.today())

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle])

        site = models.Site(name=u'ucsd', title=u'UCSD')

        t_a = date.today() + timedelta(days=5)
        patient_a = models.Patient(site=site, pid=u'12345')
        visit_a = models.Visit(patient=patient_a,
                               cycles=[cycle],
                               visit_date=t_a)

        dbsession.add_all([schema, visit_a, study])
        dbsession.flush()

        req.json_body = {
            'schema': schema.id,
        }

        with pytest.raises(HTTPBadRequest) as excinfo:
            self._call_fut(visit_a['forms'], req)

        assert 'is not part of the studies' in \
            excinfo.value.json['errors']['schema']
Exemple #19
0
    def test_has_visits(self, req, dbsession, config):
        """
        It should not allow deletion of a cycle if it has visit
        (unless administrator)
        """
        from datetime import date
        from pyramid.httpexceptions import HTTPForbidden
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'Week 1', week=1)

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle])

        patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'),
                                 pid=u'12345')

        enrollment = models.Enrollment(study=study,
                                       consent_date=date.today(),
                                       patient=patient)

        visit = models.Visit(patient=patient,
                             visit_date=date.today(),
                             cycles=[cycle])

        dbsession.add_all([study, enrollment, visit])
        dbsession.flush()

        # Should not be able to delete if not an admin
        config.testing_securitypolicy(permissive=False)
        with pytest.raises(HTTPForbidden):
            self._call_fut(cycle, req)

        config.testing_securitypolicy(permissive=True)
        self._call_fut(cycle, req)
        assert 0 == study.cycles.count()
Exemple #20
0
    def test_no_visit(self, req, dbsession):
        """
        It should allow deleting of a cycle if it has no visits
        """

        from datetime import date
        from occams import models

        cycle = models.Cycle(name='week-1', title=u'Week 1', week=1)

        study = models.Study(name=u'somestudy',
                             title=u'Some Study',
                             short_title=u'sstudy',
                             code=u'000',
                             consent_date=date.today(),
                             cycles=[cycle])

        dbsession.add_all([study])
        dbsession.flush()

        self._call_fut(cycle, req)
        assert 0 == study.cycles.count()
Exemple #21
0
    def test_visit(self, dbsession):
        """
        It should add visit-specific metadata to the report
        """
        from datetime import date, timedelta
        from occams import models as datastore
        from occams import models
        from occams.exports.schema import SchemaPlan

        schema = datastore.Schema(name=u'vitals',
                                  title=u'Vitals',
                                  publish_date=date.today(),
                                  attributes={
                                      'foo':
                                      datastore.Attribute(
                                          name='foo',
                                          title=u'',
                                          type='string',
                                          order=0,
                                      )
                                  })
        entity = datastore.Entity(collect_date=date.today(), schema=schema)
        patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'),
                                 pid=u'12345',
                                 entities=[entity])
        visit = models.Visit(
            visit_date=date.today(),
            patient=patient,
            cycles=[
                models.Cycle(name=u'study1-scr',
                             title=u'Study 1 Screening',
                             week=123,
                             study=models.Study(name=u'study1',
                                                short_title=u'S1',
                                                code=u'001',
                                                consent_date=date.today() -
                                                timedelta(365),
                                                title=u'Study 1')),
                models.Cycle(name=u'study2-wk1',
                             title=u'Study 2 Week 1',
                             week=5858,
                             study=models.Study(name=u'study21',
                                                short_title=u'S2',
                                                code=u'002',
                                                consent_date=date.today() -
                                                timedelta(365),
                                                title=u'Study 2'))
            ],
            entities=[entity])
        dbsession.add_all([schema, entity, patient, visit])
        dbsession.flush()

        plan = SchemaPlan.from_schema(dbsession, schema.name)
        codebook = list(plan.codebook())
        query = plan.data()
        codebook_columns = [c['field'] for c in codebook]
        data_columns = [c['name'] for c in query.column_descriptions]
        record = query.one()
        assert sorted(codebook_columns) == sorted(data_columns)
        assert record.site == patient.site.name
        assert record.pid == patient.pid
        assert record.enrollment is None
        cyclefmt = '{cycle.study.title}({cycle.week})'
        assert sorted(record.visit_cycles.split(';')) == \
            sorted([cyclefmt.format(cycle=c) for c in visit.cycles])
        assert str(record.visit_id) == str(visit.id)
        assert record.collect_date == entity.collect_date
Exemple #22
0
    def test_include_forms(self, req, dbsession, check_csrf_token):
        """
        It should allow the user to create cycle forms
        """
        from datetime import date, timedelta
        from occams import models as datastore
        from occams import models

        form1 = datastore.Schema(
            name='form1', title=u'', publish_date=date.today())

        form2 = datastore.Schema(
            name='form2', title=u'', publish_date=date.today())

        study = models.Study(
            name=u'somestudy',
            title=u'Some Study',
            short_title=u'sstudy',
            code=u'000',
            consent_date=date.today())

        cycle1 = models.Cycle(name='week-1', title=u'', week=1)
        cycle1.schemata.add(form1)

        cycle2 = models.Cycle(name='week-2', title=u'', week=2)
        cycle2.schemata.add(form2)

        study.cycles.append(cycle1)
        study.cycles.append(cycle2)

        patient = models.Patient(
            site=models.Site(name=u'ucsd', title=u'UCSD'),
            pid=u'12345')

        dbsession.add_all([patient, study])
        dbsession.flush()

        req.json_body = {
            'cycles': [cycle1.id],
            'visit_date': str(date.today() + timedelta(days=1)),
            'include_forms': True
        }

        res = self._call_fut(patient['visits'], req)

        assert ['form1'] == \
            [e['schema']['name'] for e in res['entities']]

        contexts = dbsession.query(datastore.Context).all()

        assert sorted(['patient', 'visit']) == \
            sorted([c.external for c in contexts])

        visit = dbsession.query(models.Visit).get(res['id'])

        # Update to demonstrate forms can still be added on edit
        req.json_body = {
            'cycles': [cycle1.id, cycle2.id],
            'visit_date': str(date.today() + timedelta(days=1)),
            'include_forms': True
        }

        res = self._call_fut(visit, req)

        assert sorted(['form1', 'form2']) == \
            sorted([e['schema']['name'] for e in res['entities']])

        contexts = dbsession.query(datastore.Context).all()

        assert sorted([(x, e['id'])
                       for e in res['entities']
                       for x in ('patient', 'visit')]) == \
            sorted([(c.external, c.entity_id) for c in contexts])