diff --git a/datasette/templates/_table.html b/datasette/templates/_table.html
index ba34b60f..f47a325f 100644
--- a/datasette/templates/_table.html
+++ b/datasette/templates/_table.html
@@ -1,6 +1,6 @@
-{% if display_rows %}
+{% if display_columns %}
-{% else %}
+{% endif %}
+{% if not display_rows %}
0 records
{% endif %}
diff --git a/datasette/templates/table.html b/datasette/templates/table.html
index 2919d306..c841e1be 100644
--- a/datasette/templates/table.html
+++ b/datasette/templates/table.html
@@ -141,7 +141,6 @@
{% if all_columns %}
-{% if display_rows %}
-{% endif %}
diff --git a/tests/test_html.py b/tests/test_html.py
index e38898da..7425692d 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -805,7 +805,7 @@ async def test_blob_download_invalid_messages(ds_client, path, expected_message)
async def test_zero_results(ds_client, path):
response = await ds_client.get(path)
soup = Soup(response.text, "html.parser")
- assert 0 == len(soup.select("table"))
+ assert 0 == len(soup.select("table tbody tr"))
assert 1 == len(soup.select("p.zero-results"))
diff --git a/tests/test_table_html.py b/tests/test_table_html.py
index d8dde593..86b9a4eb 100644
--- a/tests/test_table_html.py
+++ b/tests/test_table_html.py
@@ -752,8 +752,11 @@ async def test_column_chooser_present(ds_client):
@pytest.mark.asyncio
-async def test_mobile_column_actions_present(ds_client):
- response = await ds_client.get("/fixtures/facetable")
+@pytest.mark.parametrize(
+ "path", ["/fixtures/facetable", "/fixtures/123_starts_with_digits"]
+)
+async def test_mobile_column_actions_present(ds_client, path):
+ response = await ds_client.get(path)
assert response.status_code == 200
soup = Soup(response.text, "html.parser")
button = soup.select_one("button.column-actions-mobile.small-screen-only")
@@ -764,6 +767,25 @@ async def test_mobile_column_actions_present(ds_client):
"mobile-column-actions.js" in (script.get("src") or "")
for script in soup.find_all("script")
)
+ # mobile-column-actions.js builds its dialog from elements,
+ # so the thead must render even when the table has no rows.
+ ths = soup.select("table.rows-and-columns thead th[data-column]")
+ assert len(ths) >= 1
+
+
+@pytest.mark.asyncio
+async def test_zero_row_table_renders_thead(ds_client):
+ response = await ds_client.get("/fixtures/123_starts_with_digits")
+ assert response.status_code == 200
+ soup = Soup(response.text, "html.parser")
+ table = soup.select_one("table.rows-and-columns")
+ assert table is not None
+ column_names = [
+ th.get("data-column") for th in table.select("thead th[data-column]")
+ ]
+ assert "content" in column_names
+ assert table.select_one("tbody tr") is None
+ assert soup.select_one("p.zero-results") is not None
@pytest.mark.asyncio
|