|
10 | 10 | SinglePagePaginator, |
11 | 11 | OffsetPaginator, |
12 | 12 | PageNumberPaginator, |
| 13 | + RangePaginator, |
13 | 14 | HeaderLinkPaginator, |
14 | 15 | JSONLinkPaginator, |
15 | 16 | JSONResponseCursorPaginator, |
@@ -264,6 +265,77 @@ def test_client_pagination(self, rest_client): |
264 | 265 | assert_pagination(pages, total_pages=1) |
265 | 266 |
|
266 | 267 |
|
| 268 | +class TestRangePaginator: |
| 269 | + def test_init(self) -> None: |
| 270 | + # param_name provided, param_body_path not provided |
| 271 | + RangePaginator( |
| 272 | + param_name="page", |
| 273 | + initial_value=0, |
| 274 | + value_step=1, |
| 275 | + total_path="total", |
| 276 | + ) |
| 277 | + |
| 278 | + # param_name not provided, param_body_path provided |
| 279 | + RangePaginator( |
| 280 | + param_name=None, |
| 281 | + param_body_path="body.path", |
| 282 | + initial_value=0, |
| 283 | + value_step=1, |
| 284 | + total_path="total", |
| 285 | + ) |
| 286 | + |
| 287 | + # both param_name and param_body_path provided |
| 288 | + with pytest.raises( |
| 289 | + ValueError, match="Either 'param_name' or 'param_body_path' must be provided, not both" |
| 290 | + ): |
| 291 | + RangePaginator( |
| 292 | + param_name="page", |
| 293 | + param_body_path="body.path", |
| 294 | + initial_value=0, |
| 295 | + value_step=1, |
| 296 | + total_path="total", |
| 297 | + ) |
| 298 | + |
| 299 | + # both param_name and param_body_path are None or empty strings |
| 300 | + for param_name, param_body_path in [ |
| 301 | + (None, None), |
| 302 | + ("", None), |
| 303 | + (None, ""), |
| 304 | + ("", ""), |
| 305 | + ]: |
| 306 | + with pytest.raises( |
| 307 | + ValueError, |
| 308 | + match="Either 'param_name' or 'param_body_path' must be provided, not both", |
| 309 | + ): |
| 310 | + RangePaginator( |
| 311 | + param_name=param_name, |
| 312 | + param_body_path=param_body_path, |
| 313 | + initial_value=0, |
| 314 | + value_step=1, |
| 315 | + total_path="total", |
| 316 | + ) |
| 317 | + |
| 318 | + with pytest.raises( |
| 319 | + ValueError, match="Either 'param_name' or 'param_body_path' must be provided, not both" |
| 320 | + ): |
| 321 | + RangePaginator( |
| 322 | + param_name=None, |
| 323 | + param_body_path=None, |
| 324 | + initial_value=0, |
| 325 | + value_step=1, |
| 326 | + total_path="total", |
| 327 | + ) |
| 328 | + |
| 329 | + def test_range_paginator_update(self) -> None: |
| 330 | + request = Mock(Request) |
| 331 | + request.json = {} |
| 332 | + with pytest.raises(ValueError, match="param_name.*must not be empty"): |
| 333 | + RangePaginator._update_request_with_param_name(request, "", 0) |
| 334 | + |
| 335 | + with pytest.raises(ValueError, match="body_path.*must not be empty"): |
| 336 | + RangePaginator._update_request_with_body_path(request, "", 0) |
| 337 | + |
| 338 | + |
267 | 339 | @pytest.mark.usefixtures("mock_api_server") |
268 | 340 | class TestOffsetPaginator: |
269 | 341 | def test_update_state(self): |
@@ -499,6 +571,60 @@ def test_guarantee_termination(self): |
499 | 571 | " must be provided" |
500 | 572 | ) |
501 | 573 |
|
| 574 | + @pytest.mark.parametrize( |
| 575 | + "offset_param,offset_body_path", |
| 576 | + [ |
| 577 | + (None, None), |
| 578 | + ("", None), |
| 579 | + (None, ""), |
| 580 | + ("", ""), |
| 581 | + ], |
| 582 | + ) |
| 583 | + def test_empty_offset_params(self, offset_param, offset_body_path) -> None: |
| 584 | + if offset_param is None and offset_body_path is None: |
| 585 | + # Fallback to default 'offset' param |
| 586 | + paginator = OffsetPaginator( |
| 587 | + limit=100, offset_param=offset_param, offset_body_path=offset_body_path |
| 588 | + ) |
| 589 | + assert paginator.param_name == "offset" |
| 590 | + assert paginator.param_body_path is None |
| 591 | + else: |
| 592 | + with pytest.raises( |
| 593 | + ValueError, match="Either 'offset_param' or 'offset_body_path' must be provided.*" |
| 594 | + ): |
| 595 | + OffsetPaginator( |
| 596 | + limit=100, |
| 597 | + offset_param=offset_param, |
| 598 | + offset_body_path=offset_body_path, |
| 599 | + ) |
| 600 | + |
| 601 | + @pytest.mark.parametrize( |
| 602 | + "limit_param,limit_body_path", |
| 603 | + [ |
| 604 | + (None, None), |
| 605 | + ("", None), |
| 606 | + (None, ""), |
| 607 | + ("", ""), |
| 608 | + ], |
| 609 | + ) |
| 610 | + def test_empty_limit_params(self, limit_param, limit_body_path) -> None: |
| 611 | + if limit_param is None and limit_body_path is None: |
| 612 | + # Fallback to default 'limit' param |
| 613 | + paginator = OffsetPaginator( |
| 614 | + limit=100, limit_param=limit_param, limit_body_path=limit_body_path |
| 615 | + ) |
| 616 | + assert paginator.limit_param == "limit" |
| 617 | + assert paginator.limit_body_path is None |
| 618 | + else: |
| 619 | + with pytest.raises( |
| 620 | + ValueError, match="Either 'limit_param' or 'limit_body_path' must be provided.*" |
| 621 | + ): |
| 622 | + OffsetPaginator( |
| 623 | + limit=100, |
| 624 | + limit_param=limit_param, |
| 625 | + limit_body_path=limit_body_path, |
| 626 | + ) |
| 627 | + |
502 | 628 |
|
503 | 629 | @pytest.mark.usefixtures("mock_api_server") |
504 | 630 | class TestPageNumberPaginator: |
@@ -761,6 +887,30 @@ def test_guarantee_termination(self): |
761 | 887 | " must be provided" |
762 | 888 | ) |
763 | 889 |
|
| 890 | + @pytest.mark.parametrize( |
| 891 | + "page_param,page_body_path", |
| 892 | + [ |
| 893 | + (None, None), |
| 894 | + ("", None), |
| 895 | + (None, ""), |
| 896 | + ("", ""), |
| 897 | + ], |
| 898 | + ) |
| 899 | + def test_empty_params(self, page_param, page_body_path) -> None: |
| 900 | + if page_param is None and page_body_path is None: |
| 901 | + # Fallback to default 'page' param |
| 902 | + paginator = PageNumberPaginator(page_param=page_param, page_body_path=page_body_path) |
| 903 | + assert paginator.param_name == "page" |
| 904 | + assert paginator.param_body_path is None |
| 905 | + else: |
| 906 | + with pytest.raises( |
| 907 | + ValueError, match="Either 'page_param' or 'page_body_path' must be provided.*" |
| 908 | + ): |
| 909 | + PageNumberPaginator( |
| 910 | + page_param=page_param, |
| 911 | + page_body_path=page_body_path, |
| 912 | + ) |
| 913 | + |
764 | 914 |
|
765 | 915 | @pytest.mark.usefixtures("mock_api_server") |
766 | 916 | class TestJSONResponseCursorPaginator: |
|
0 commit comments