Skip to content

Commit

Permalink
Assorted hacks to get the tests working with computed attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
multimeric committed Feb 28, 2020
1 parent da45155 commit 6f4f2bd
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 17 deletions.
6 changes: 3 additions & 3 deletions megaqc/rest_api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ class Meta:
id = f.Integer(attribute='sample_data_type_id', allow_none=True, as_string=True)
section = f.String(attribute='data_section')
key = f.String(attribute='data_key')
nice_key = f.String()
nice_section = f.String()
nice_name = f.String()
nice_key = f.String(dump_only=True)
nice_section = f.String(dump_only=True)
nice_name = f.String(dump_only=True)


class SampleDataSchema(Schema):
Expand Down
6 changes: 5 additions & 1 deletion megaqc/rest_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from flask import Blueprint
from flask import request, jsonify, make_response
from flask_login import current_user
from marshmallow.utils import INCLUDE
from marshmallow.utils import INCLUDE, EXCLUDE
from marshmallow_jsonapi.exceptions import IncorrectTypeError

import megaqc.user.models as user_models
Expand Down Expand Up @@ -212,6 +212,10 @@ class DataType(ResourceDetail):


class DataTypeList(ResourceList):
post_schema_kwargs = {
# 'unknown': EXCLUDE
# 'exclude': ['nice_key', 'nice_section', 'nice_name']
}
view_kwargs = True
schema = schemas.SampleDataTypeSchema
data_layer = dict(
Expand Down
2 changes: 1 addition & 1 deletion src/trend/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function TrendForm({dataTypes, onSubmit}) {
}}
validationSchema={
Yup.object().shape({
fields: Yup.array().min(1).label('Fields'),
fields: Yup.array().min(1).label('Data Types'),
// Outlier has its own internal field validation
centerLine: Yup.string().oneOf(['mean', 'median', 'none']).label('Center Line'),
controlLimits: Yup.bool().label('Show Control Limits'),
Expand Down
2 changes: 1 addition & 1 deletion src/trend/sampleFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function SampleFilter(props) {

const [sampleFilters, setSampleFilters] = useState([]);
const [selectedFilter, setSelectedFilter] = useState(null);
const [selectedGroup, setSelectedGroup] = useState(null);
const [selectedGroup, setSelectedGroup] = useState("Global");
const [modalOpen, setModalOpen] = useState(false);

function updateFilters() {
Expand Down
52 changes: 43 additions & 9 deletions tests/api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,40 @@
import pytest
from flask import url_for
from sqlalchemy import inspect
from sqlalchemy.orm import RelationshipProperty
from marshmallow import EXCLUDE

from tests import factories


def unset_dump_only(schema):
for field in schema.declared_fields.values():
field.dump_only = False
schema._init_fields()


def dump_only_fields(schema):
"""
Returns a list of field names for the dump_only fields
"""
return [key for key, field in schema._declared_fields.items() if field.dump_only]


def object_as_dict(obj, relationships=False):
"""
Converts an SQLAlchemy instance to a dictionary
:param relationships: If true, also include relationships in the output dict
"""
ret = {c.key: getattr(obj, c.key) for c in inspect(obj).mapper.column_attrs}
if relationships:
ret.update(
{c.key: getattr(obj, c.key) for c in inspect(obj).mapper.relationships})
return ret
properties = inspect(obj).mapper.all_orm_descriptors

if not relationships:
properties = {
key: value for key, value in properties.items()
if not hasattr(value, 'prop') or not isinstance(value.prop,
RelationshipProperty)
}

return {key: getattr(obj, key) for key, value in properties.items()}


def resource_from_endpoint(app, endpoint):
Expand Down Expand Up @@ -152,7 +172,13 @@ def test_get_many_resources(endpoint, session, client, admin_token, app):
ret = rv.json
del ret['meta']
del ret['jsonapi']
data = resource.schema(many=True).load(ret)
schema = resource.schema(many=True)

# We actually want to load the "dump_only" fields here, so that we can validate they
# were dumped correctly. We don't normally want to do this, which is why this is a
# test function only
unset_dump_only(schema)
data = schema.load(ret)

# Check we got at least one instance
assert len(data) > 0
Expand Down Expand Up @@ -252,7 +278,10 @@ def test_get_single_resource(endpoint, session, client, admin_token, app):
# Load the data using the schema. This also does data validation
ret = rv.json
del ret['jsonapi']
data = resource.schema(many=False).load(ret)
schema = resource.schema(many=False)
# See above for explanation
unset_dump_only(schema)
data = schema.load(ret)

# Check we got at least one instance
assert is_matching_resource(data, instance, model)
Expand Down Expand Up @@ -323,7 +352,12 @@ def test_post_resource(endpoint, admin_token, session, client, app):
# clone = clone_model(instance)
session.expunge(clone)

request = resource.schema(many=False, use_links=False).dump(clone)
# If we're pretending to be a client, we don't want to send the dump_only fields
# that might be computed
dump_only = dump_only_fields(resource.schema)
request = resource.schema(many=False, use_links=False, exclude=dump_only).dump(
clone
)

count_1 = session.query(model).count()

Expand All @@ -342,4 +376,4 @@ def test_post_resource(endpoint, admin_token, session, client, app):
assert count_2 - count_1 == 1

# Validate the returned data
data = resource.schema(many=False).load(ret)
data = resource.schema(many=False, unknown=EXCLUDE).load(ret)
9 changes: 7 additions & 2 deletions tests/api/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ def test_get_trend_series(db, client):
# plots = jpi.get('plots/trends/series')
url = url_for(
'rest_api.trend_data',
filter=json.dumps([]),
fields=json.dumps([data_type.data_key])
**{
'filter': json.dumps([]),
'fields': json.dumps([data_type.data_key]),
'control_limits[enabled]': True,
'control_limits[sigma]': 3,
'center_line': 'mean'
}
)
response = client.get(url, headers={'Content-Type': 'application/json'})

Expand Down

0 comments on commit 6f4f2bd

Please sign in to comment.