Skip to content

Commit a29df1a

Browse files
committed
test: add missing test cases for advanced slice, filters, and more
1 parent 14f282f commit a29df1a

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

tests/test_basic.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,98 @@ def custom_eval(expr, *args, **kwargs):
387387
result = jp.parse(data, eval_func=custom_eval)
388388
assert len(result) == 2
389389
assert len(eval_calls) > 0
390+
391+
392+
class TestSliceAdvanced:
393+
"""Test advanced slice operations."""
394+
395+
def test_slice_reverse(self):
396+
data = {"items": [0, 1, 2, 3, 4]}
397+
assert JSONPath("$.items[::-1]").parse(data) == [4, 3, 2, 1, 0]
398+
399+
def test_slice_reverse_step(self):
400+
data = {"items": [0, 1, 2, 3, 4]}
401+
assert JSONPath("$.items[::-2]").parse(data) == [4, 2, 0]
402+
403+
def test_slice_negative_start(self):
404+
data = {"items": [0, 1, 2, 3, 4]}
405+
assert JSONPath("$.items[-2:]").parse(data) == [3, 4]
406+
407+
def test_slice_negative_end(self):
408+
data = {"items": [0, 1, 2, 3, 4]}
409+
assert JSONPath("$.items[:-2]").parse(data) == [0, 1, 2]
410+
411+
412+
class TestFilterAdvanced:
413+
"""Test advanced filter operations."""
414+
415+
def test_filter_not_in_operator(self):
416+
data = {"items": [{"tags": ["a", "b"]}, {"tags": ["c", "d"]}]}
417+
assert JSONPath("$.items[?('a' not in @.tags)].tags").parse(data) == [["c", "d"]]
418+
419+
def test_filter_not_operator(self):
420+
data = {"items": [{"active": True}, {"active": False}]}
421+
assert JSONPath("$.items[?(not @.active)]").parse(data) == [{"active": False}]
422+
423+
def test_filter_is_operator(self):
424+
data = {"items": [{"v": None}, {"v": 1}]}
425+
assert JSONPath("$.items[?(@.v is None)]").parse(data) == [{"v": None}]
426+
427+
def test_filter_is_not_operator(self):
428+
data = {"items": [{"v": None}, {"v": 1}]}
429+
assert JSONPath("$.items[?(@.v is not None)]").parse(data) == [{"v": 1}]
430+
431+
def test_filter_nested_attribute(self):
432+
data = {"items": [{"x": {"y": 1}}, {"x": {"y": 2}}]}
433+
assert JSONPath("$.items[?(@.x.y > 1)]").parse(data) == [{"x": {"y": 2}}]
434+
435+
def test_filter_bracket_notation(self):
436+
data = {"items": [{"a-b": 1}, {"a-b": 2}]}
437+
assert JSONPath("$.items[?(@['a-b'] > 1)]").parse(data) == [{"a-b": 2}]
438+
439+
440+
class TestRecursiveDescentAdvanced:
441+
"""Test advanced recursive descent operations."""
442+
443+
def test_recursive_with_bracket(self):
444+
data = {"a": {"b": 1}, "c": {"b": 2}}
445+
assert sorted(JSONPath("$..['b']").parse(data)) == [1, 2]
446+
447+
def test_recursive_with_filter(self):
448+
data = {"items": [{"v": 1}, {"v": 2}]}
449+
result = JSONPath("$.items[*][?(@.v > 1)]").parse(data)
450+
assert result == [{"v": 2}]
451+
452+
def test_recursive_multiple_levels(self):
453+
data = {"a": {"b": {"c": {"d": 1}}}}
454+
assert JSONPath("$..d").parse(data) == [1]
455+
456+
457+
class TestJSONPathTypeError:
458+
"""Test JSONPathTypeError exception."""
459+
460+
def test_sort_incompatible_types(self):
461+
from jsonpath import JSONPathTypeError
462+
463+
# Sorting with mixed types that can't be compared
464+
data = {"items": [{"v": "a"}, {"v": 1}]}
465+
with pytest.raises(JSONPathTypeError, match="not possible to compare"):
466+
JSONPath("$.items[/(v)]").parse(data)
467+
468+
469+
class TestInstanceMethod:
470+
"""Test JSONPath instance methods."""
471+
472+
def test_search_method(self):
473+
"""JSONPath.search() is an alias for parse()."""
474+
data = {"a": 1}
475+
jp = JSONPath("$.a")
476+
assert jp.search(data) == [1]
477+
assert jp.search(data, "PATH") == ["$.a"]
478+
479+
def test_parse_reuse(self):
480+
"""Same JSONPath instance can be reused for multiple parse calls."""
481+
jp = JSONPath("$.a")
482+
assert jp.parse({"a": 1}) == [1]
483+
assert jp.parse({"a": 2}) == [2]
484+
assert jp.parse({"a": 3}) == [3]

0 commit comments

Comments
 (0)