mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-23 01:38:11 +08:00
This splits the backend into two parts: the local backend for desktop cellxgene and the AWS backend for hosted cellxgene. The local backend is in local_server while the hosted remains in server. The general idea is to copy everything from server to local_server, pull unneeded stuff out of local_server, and keep server as-is for this PR. Not touching server means all the infra and deployment code will continue working just as it did before so we can make those changes incrementally.
80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
import unittest
|
|
from urllib.parse import parse_qs
|
|
from werkzeug.datastructures import MultiDict
|
|
from local_server.common.rest import _query_parameter_to_filter
|
|
from local_server.common.errors import FilterError
|
|
|
|
|
|
def _qsparse(qs):
|
|
""" emulate what Flask/Werkzeug do to our QS """
|
|
return MultiDict(parse_qs(qs))
|
|
|
|
|
|
class FilterParseTests(unittest.TestCase):
|
|
""" Test cases for various filter parsing """
|
|
|
|
def test_queryparam_to_filter_parse(self):
|
|
# categories
|
|
self.assertEqual(
|
|
_query_parameter_to_filter(_qsparse("obs:foo=bar&var:baz=133&var:baz=A&obs:baz=foo")),
|
|
{
|
|
"obs": {"annotation_value": [{"name": "foo", "values": ["bar"]}, {"name": "baz", "values": ["foo"]}]},
|
|
"var": {"annotation_value": [{"name": "baz", "values": ["133", "A"]}]},
|
|
},
|
|
)
|
|
|
|
# ranges
|
|
self.assertEqual(
|
|
_query_parameter_to_filter(_qsparse("obs:A=1,99&obs:B=*,100&obs:C=0,*")),
|
|
{
|
|
"obs": {
|
|
"annotation_value": [
|
|
{"name": "A", "min": 1, "max": 99.0},
|
|
{"name": "B", "max": 100.0},
|
|
{"name": "C", "min": 0.0},
|
|
]
|
|
},
|
|
},
|
|
)
|
|
|
|
# combo
|
|
self.assertEqual(
|
|
_query_parameter_to_filter(_qsparse("var:B=YES&var:A=1,99&var:B=NO")),
|
|
{
|
|
"var": {
|
|
"annotation_value": [
|
|
{"name": "B", "values": ["YES", "NO"]},
|
|
{"name": "A", "min": 1.0, "max": 99.0},
|
|
]
|
|
},
|
|
},
|
|
)
|
|
|
|
def test_queryparam_to_filter_escaping(self):
|
|
self.assertEqual(
|
|
_query_parameter_to_filter(_qsparse("obs:var=%2521%252C%253AOK%253D&obs:A%2521=YO")),
|
|
{"obs": {"annotation_value": [{"name": "var", "values": ["!,:OK="]}, {"name": "A!", "values": ["YO"]}]}},
|
|
)
|
|
|
|
def test_queryparam_to_filter_errors(self):
|
|
|
|
# should raise FilterError
|
|
filter_errors = [
|
|
"foo=bar", # no axis
|
|
"X=&Y=3", # no value
|
|
"X&Y=3", # no value
|
|
"moo:foo=bar", # bad axis
|
|
"obs:x=1,A", # non-numeric range
|
|
"var:X=1,2&var:X=3,4", # duplicate ranges
|
|
"var:Y=,",
|
|
"var:Y=2,",
|
|
"var:Y=,5",
|
|
"var:Y=*,",
|
|
"var:Y=,*",
|
|
"var:Y=*,*",
|
|
]
|
|
|
|
for qs in filter_errors:
|
|
with self.assertRaises(FilterError):
|
|
_query_parameter_to_filter(_qsparse(qs))
|