def test_missing_required_params(self, client, entities, endpoint, method,
                                     field):
        """ Tests missing required parameters """
        # Setup inputs
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        inputs.pop(field, None)

        # Setup endpoint
        url = endpoint
        action = 'create'
        if method.lower() in {'put'}:
            action = 'update'
            kf_id = entities.get('kf_ids').get(endpoint)
            url = '{}/{}'.format(endpoint, kf_id)
        call_func = getattr(client, method.lower())
        resp = call_func(url,
                         data=json.dumps(inputs),
                         headers={'Content-Type': 'application/json'})

        body = json.loads(resp.data.decode('utf-8'))
        assert body['_status']['code'] == 400
        assert 'could not {} '.format(action) in body['_status']['message']
    def test_bad_input(self, client, entities, endpoint, invalid_params,
                       method):
        """ Tests bad inputs """
        # Setup inputs
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        inputs.update(invalid_params)

        # Setup endpoint
        url = endpoint
        action = 'create'
        if method.lower() in {'put', 'patch'}:
            action = 'update'
            kf_id = entity.kf_id
            url = '{}/{}'.format(endpoint, kf_id)
        call_func = getattr(client, method.lower())

        # Send request
        resp = call_func(url,
                         data=json.dumps(inputs),
                         headers={'Content-Type': 'application/json'})

        body = json.loads(resp.data.decode('utf-8'))
        assert body['_status']['code'] == 400
        assert 'could not {} '.format(action) in body['_status']['message']
    def test_unknown_field(self, client, entities, endpoint, method):
        """ Test that unknown fields are rejected when trying to create  """
        # Setup inputs
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        inputs.update({'blah': 'test'})

        # Setup endpoint
        url = endpoint
        action = 'create'
        if method.lower() in {'put', 'patch'}:
            action = 'update'
            kf_id = entity.kf_id
            url = '{}/{}'.format(endpoint, kf_id)
        call_func = getattr(client, method.lower())
        resp = call_func(url,
                         data=json.dumps(inputs),
                         headers={'Content-Type': 'application/json'})

        body = json.loads(resp.data.decode('utf-8'))
        assert body['_status']['code'] == 400
        assert 'could not {} '.format(action) in body['_status']['message']
        assert 'Unknown field' in body['_status']['message']
    def test_read_only(self, client, entities, endpoint, method, fields):
        """ Test that given fields can not be written or modified """
        # Setup inputs
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        [inputs.update({field: 'test'}) for field in fields]

        # Setup enpdoint
        url = endpoint
        method_name = method.lower()
        call_func = getattr(client, method_name)
        kwargs = {
            'data': json.dumps(inputs),
            'headers': {
                'Content-Type': 'application/json'
            }
        }
        if method_name in {'put', 'patch'}:
            kf_id = entity.kf_id
            url = '{}/{}'.format(endpoint, kf_id)

        # Send request
        resp = call_func(url, **kwargs)
        body = json.loads(resp.data.decode('utf-8'))

        if 'results' not in body:
            assert ('error saving' in body['_status']['message']
                    or 'already exists' in body['_status']['message'])
            return
        for field in fields:
            assert (field not in body['results']
                    or body['results'][field] != 'test')
    def test_uniqueness_constraints(self, client, entities, endpoint):
        """ Test integrity error from uniqueness violations """
        # _add_foreign_keys is destructive to ENTITY_PARAMS['fields'][endpoint]
        # state used by other tests, so deepcopy it here to prevent side
        # effects.
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        response = client.post(
            endpoint, data=json.dumps(inputs),
            headers={'Content-Type': 'application/json'}
        )

        assert response.status_code == 400
        response = json.loads(response.data.decode("utf-8"))
        assert CONSTRAINT_ERR_RE.match(response['_status']['message'])
    def test_bad_foreign_key(self, client, entities, endpoint, method, field):
        """
        Test bad foreign key
        Foregin key is a valid kf_id but refers an entity that doesn't exist
        """
        # Setup inputs
        inputs = ENTITY_PARAMS['fields'][endpoint].copy()
        model_cls = ENDPOINT_ENTITY_MAP.get(endpoint)
        entity = entities.get(model_cls)[0]
        _add_foreign_keys(inputs, entity)
        inputs.update({field: id_service.kf_id_generator('ZZ')()})

        # Setup endpoint
        url = endpoint
        if method.lower() in {'put', 'patch'}:
            url = '{}/{}'.format(endpoint, entity.kf_id)
        call_func = getattr(client, method.lower())
        resp = call_func(url,
                         data=json.dumps(inputs),
                         headers={'Content-Type': 'application/json'})

        body = json.loads(resp.data.decode('utf-8'))
        assert body['_status']['code'] == 400
        assert 'does not exist' in body['_status']['message']