datasette/tests
feiiiiii5 3bc7e7517a
Keep an empty-string keyset pagination cursor, closes #2967
path_from_row_pks() returns "" for a row whose only primary key value is
the empty string, and "" is a legitimate _next= cursor. Both the site
that emits the token and the site that reads it back tested it for
truthiness, so the token was discarded.

Emitting:

    "next": next_value and str(next_value) or None

turns "" into None, while next_url is still built a few lines earlier
and stays non-null. docs/json_api.rst:99 says both are null on the final
page, so the response contradicted its own documentation. Reading back,
"if _next:" then ignored the cursor and the query returned page 1
again, so a client following next_url looped on the first row forever.

    CREATE TABLE t (id TEXT PRIMARY KEY);
    INSERT INTO t (id) VALUES ('a'), (''), ('c'), ('d'), 'e');

    /d/t.json?_size=1   rows ['']   next=None   next_url=...&_next=
    following it       rows ['']   next=None   next_url=...&_next=

None is the no-cursor sentinel: it is initialised to None at
table.py:2508 and nothing assigns "" to it deliberately. The same
function already asks this correctly at table.py:2536
("if prefix is None: prefix = '\'").

A bare ?_next= with no value now means "rows after the empty primary
key" rather than being ignored, which is the only coherent reading of
an empty cursor. _next=a and _next=zzz are unchanged.

No docs change: json_api.rst already describes the fixed behaviour.

Test: tests/test_table_api.py::test_paginate_table_with_empty_string_primary_key
walks the pages and fails on cec5e6b2 with

    assert '_next=None' in '...?_size=1&_next='

pytest -n auto -m 'not serial' 2782 passed, pytest -m serial 40 passed.
black, ruff, cog --check and codespell clean.
2026-09-29 00:42:01 +08:00
..
plugins Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_templates Fix handling of nested custom page wildcard paths, closes #996 2020-10-07 15:51:11 -07:00
__init__.py Broke up test_app into test_api and test_html 2017-12-15 04:08:24 -08:00
build_small_spatialite_db.py New run_sanity_checks mechanism, for SpatiLite 2019-05-11 15:55:30 -07:00
conftest.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
ext.c Add new entrypoint option to --load-extensions. (#1789) 2022-08-23 11:34:30 -07:00
fixtures.py Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -07:00
spatialite.db New run_sanity_checks mechanism, for SpatiLite 2019-05-11 15:55:30 -07:00
test-datasette-load-plugins.sh fix (typo): Corrected spelling of 'environments' (#2268) 2024-02-19 14:41:32 -08:00
test_actions_sql.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_actor_restriction_bug.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_allowed_many.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_allowed_resources.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_api.py Limit derived-table permissions to one source hop 2026-09-10 16:52:52 -07:00
test_api_write.py Fix for GHSA-h547-rmjf-5m2m 2026-09-16 16:43:34 -07:00
test_auth.py Refuse API token creation from restricted actors 2026-09-09 08:38:40 -07:00
test_autocomplete.py Add "ok": true to every JSON object success response 2026-07-04 13:40:05 +00:00
test_background_tasks.py Add datasette.add_background_task() with supervised launch after startup (#2889) 2026-09-15 10:55:54 -07:00
test_base_view.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_cli.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_cli_serve_get.py Add datasette.add_background_task() with supervised launch after startup (#2889) 2026-09-15 10:55:54 -07:00
test_cli_serve_server.py Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -07:00
test_column_types.py Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -07:00
test_config_dir.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_config_permission_rules.py Run black formatter 2025-10-25 15:38:07 -07:00
test_crossdb.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_csrf_middleware.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_csv.py Return CSV errors as plain text, closes #2129 2026-09-15 15:53:10 -07:00
test_custom_pages.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_datasette_https_server.sh More robust test_datasette_https_server.sh test 2026-06-22 10:11:56 -07:00
test_debug_autocomplete.py Autocomplete widget and /-/debug/autocomplete test page 2026-06-13 22:59:37 -07:00
test_default_deny.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_docs.py Use cog to show default values in settings.rst 2026-09-17 12:30:47 -07:00
test_docs_plugins.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_error_shape.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_extras.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_facets.py Don't 500 on ?_facets=x 2026-09-24 11:34:45 -07:00
test_fd_leak.py FD-leak regression test for Datasette.close() 2026-04-16 20:18:05 -07:00
test_filters.py Fix for SQL injection issue in table filters, refs #2868 2026-08-06 11:19:50 -07:00
test_fixtures.py datasette.fixtures module, closes #2733 2026-05-21 23:05:37 -07:00
test_fts_permissions.py Limit derived-table permissions to one source hop 2026-09-10 16:52:52 -07:00
test_html.py Fix missing space before the view count on the index page (#2951) 2026-09-24 11:50:01 -07:00
test_http_span.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_internal_db.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_internals_database.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_internals_datasette.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_internals_datasette_client.py Migrate from httpx to httpx2, closes #2879 2026-09-10 19:44:49 -07:00
test_internals_request.py Make request header lookups case-insensitive 2026-09-16 10:27:35 -07:00
test_internals_response.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_internals_urls.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_jump.py Autocomplete widget and /-/debug/autocomplete test page 2026-06-13 22:59:37 -07:00
test_label_column_for_table.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_lifespan.py Ensure startup() runs before any plugin ASGI middleware (#2891) 2026-09-15 11:22:45 -07:00
test_load_extensions.py Disable extension loading once --load-extension extensions are loaded 2026-09-08 10:48:19 -07:00
test_messages.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_multipart.py Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -07:00
test_numeric_filter_values.py Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -07:00
test_package.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_permission_endpoints.py Require view-instance permission for /-/allowed 2026-09-08 10:48:19 -07:00
test_permissions.py Add /-/tasks introspection endpoint for supervised background tasks (#2892) 2026-09-15 11:56:53 -07:00
test_playwright.py Rename modal trigger option to returnFocusTo, refs #2790 2026-09-17 15:46:34 -07:00
test_plugins.py Allow extra_template_vars to resolve to None 2026-09-16 10:30:11 -07:00
test_pr76_fts_policy.py Limit derived-table permissions to one source hop 2026-09-10 16:52:52 -07:00
test_pr76_statistics_policy.py Deny SQLite statistics table access through a default hook 2026-09-10 16:52:25 -07:00
test_publish_cloudrun.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_publish_heroku.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_pytest_autoclose_plugin.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_queries.py execute-write: Check view-table for every table in a CREATE VIEW 2026-09-08 10:48:19 -07:00
test_restriction_sql.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_routes.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_schema_endpoints.py Only allow /db/name/-/schema against tables and views 2026-09-08 10:48:20 -07:00
test_search_tables.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_shutdown.py Add shutdown() plugin hook with ordered graceful teardown (#2890) 2026-09-15 11:09:57 -07:00
test_spatialite.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_stored_queries.py Protect personalized dynamic responses from shared caching 2026-09-08 21:16:36 -07:00
test_success_envelope.py Add /-/tasks introspection endpoint for supervised background tasks (#2892) 2026-09-15 11:56:53 -07:00
test_table_api.py Keep an empty-string keyset pagination cursor, closes #2967 2026-09-29 00:42:01 +08:00
test_table_count.py Tests for table count endpoint, refs #2914 2026-09-15 12:21:36 -07:00
test_table_html.py Case insensitive check for foreign key tables 2026-09-24 12:10:42 -07:00
test_table_resource_identity.py Match table permission identities using SQLite case semantics 2026-09-09 08:39:03 -07:00
test_tasks_endpoint.py Add /-/tasks introspection endpoint for supervised background tasks (#2892) 2026-09-15 11:56:53 -07:00
test_telemetry.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_telemetry_metrics.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_telemetry_registry.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_telemetry_testing_kit.py Simplify code comments added since 1.0a40 (#2957) 2026-09-24 13:52:29 -07:00
test_template_context.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_token_handler.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_tracer.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_utils.py Fix for GHSA-h547-rmjf-5m2m 2026-09-16 16:43:34 -07:00
test_utils_check_callable.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_utils_permissions.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
test_utils_sql_analysis.py Fix CREATE VIEW analysis on Python 3.10 2026-09-08 10:49:52 -07:00
test_write_sql_operation_decisions.py Refactored write decision tests 2026-05-28 12:09:20 -07:00
test_write_wrapper.py Keep alter-table changes rollbackable by write wrappers 2026-09-16 14:40:50 -07:00
utils.py From 409 warnings down to 52 warnings. 2026-04-14 18:46:47 -07:00