chore: import upstream snapshot with attribution
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,442 @@
|
||||
"""
|
||||
Tests for Collection CRUD API endpoints.
|
||||
|
||||
Tests the following endpoints:
|
||||
- GET /library/api/collections
|
||||
- POST /library/api/collections
|
||||
- PUT /library/api/collections/<id>
|
||||
- DELETE /library/api/collections/<id>
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
|
||||
# Import helpers from conftest
|
||||
from .conftest import delete_test_collection
|
||||
|
||||
|
||||
class TestGetCollections:
|
||||
"""Tests for GET /library/api/collections endpoint."""
|
||||
|
||||
def test_get_collections_unauthenticated(self, client):
|
||||
"""Unauthenticated request is rejected."""
|
||||
response = client.get("/library/api/collections")
|
||||
# Should redirect to login or return 401
|
||||
assert response.status_code in [302, 401]
|
||||
|
||||
def test_get_collections_authenticated_empty(self, authenticated_client):
|
||||
"""Returns collections list (may include default Library)."""
|
||||
response = authenticated_client.get("/library/api/collections")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert "collections" in data
|
||||
assert isinstance(data["collections"], list)
|
||||
|
||||
def test_get_collections_with_data(
|
||||
self, authenticated_client, create_collection_helper
|
||||
):
|
||||
"""Returns created collections."""
|
||||
# Create a test collection
|
||||
created = create_collection_helper(
|
||||
name="API Test Collection",
|
||||
description="Testing GET endpoint",
|
||||
)
|
||||
assert created is not None
|
||||
|
||||
response = authenticated_client.get("/library/api/collections")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
|
||||
# Find our created collection
|
||||
collection_names = [c["name"] for c in data["collections"]]
|
||||
assert "API Test Collection" in collection_names
|
||||
|
||||
def test_get_collections_includes_metadata(
|
||||
self, authenticated_client, create_collection_helper
|
||||
):
|
||||
"""Collections include required metadata fields."""
|
||||
created = create_collection_helper()
|
||||
assert created is not None
|
||||
|
||||
response = authenticated_client.get("/library/api/collections")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert len(data["collections"]) > 0
|
||||
|
||||
# Check metadata fields
|
||||
coll = data["collections"][0]
|
||||
assert "id" in coll
|
||||
assert "name" in coll
|
||||
assert "description" in coll
|
||||
assert "created_at" in coll
|
||||
assert "collection_type" in coll
|
||||
assert "document_count" in coll
|
||||
|
||||
|
||||
class TestCreateCollection:
|
||||
"""Tests for POST /library/api/collections endpoint."""
|
||||
|
||||
def test_create_collection_unauthenticated(self, client):
|
||||
"""Unauthenticated request is rejected."""
|
||||
response = client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": "Test", "description": "Test"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert response.status_code in [302, 401]
|
||||
|
||||
def test_create_collection_success(self, authenticated_client):
|
||||
"""Successfully creates a new collection."""
|
||||
unique_name = f"Test Collection {uuid.uuid4().hex[:8]}"
|
||||
|
||||
response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={
|
||||
"name": unique_name,
|
||||
"description": "A test collection",
|
||||
"type": "user_uploads",
|
||||
},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert data["collection"]["name"] == unique_name
|
||||
assert data["collection"]["description"] == "A test collection"
|
||||
assert "id" in data["collection"]
|
||||
|
||||
# Cleanup
|
||||
delete_test_collection(authenticated_client, data["collection"]["id"])
|
||||
|
||||
def test_create_collection_defaults_private(self, authenticated_client):
|
||||
"""A new collection with no is_public flag defaults to private."""
|
||||
name = f"Priv {uuid.uuid4().hex[:8]}"
|
||||
resp = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": name},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
coll = resp.get_json()["collection"]
|
||||
assert coll["is_public"] is False
|
||||
delete_test_collection(authenticated_client, coll["id"])
|
||||
|
||||
def test_create_and_toggle_collection_is_public(self, authenticated_client):
|
||||
"""is_public can be set at create and flipped via PUT, and is
|
||||
reflected in the list API."""
|
||||
name = f"Pub {uuid.uuid4().hex[:8]}"
|
||||
resp = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": name, "is_public": True},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
coll = resp.get_json()["collection"]
|
||||
cid = coll["id"]
|
||||
assert coll["is_public"] is True
|
||||
|
||||
# List reflects it
|
||||
listing = authenticated_client.get(
|
||||
"/library/api/collections"
|
||||
).get_json()["collections"]
|
||||
match = next(c for c in listing if c["id"] == cid)
|
||||
assert match["is_public"] is True
|
||||
|
||||
# The collection-details load path (documents endpoint) also exposes
|
||||
# is_public so the details-page toggle can reflect current state.
|
||||
docs = authenticated_client.get(
|
||||
f"/library/api/collections/{cid}/documents"
|
||||
)
|
||||
assert docs.status_code == 200
|
||||
assert docs.get_json()["collection"]["is_public"] is True
|
||||
|
||||
# Flip back to private via PUT
|
||||
put = authenticated_client.put(
|
||||
f"/library/api/collections/{cid}",
|
||||
json={"is_public": False},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert put.status_code == 200
|
||||
assert put.get_json()["collection"]["is_public"] is False
|
||||
|
||||
delete_test_collection(authenticated_client, cid)
|
||||
|
||||
def test_create_collection_empty_name(self, authenticated_client):
|
||||
"""Rejects collection with empty name."""
|
||||
response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": "", "description": "No name"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
assert (
|
||||
"required" in data["error"].lower()
|
||||
or "name" in data["error"].lower()
|
||||
)
|
||||
|
||||
def test_create_collection_whitespace_name(self, authenticated_client):
|
||||
"""Rejects collection with whitespace-only name."""
|
||||
response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": " ", "description": "Whitespace name"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_create_collection_duplicate_name(self, authenticated_client):
|
||||
"""Rejects collection with duplicate name."""
|
||||
unique_name = f"Duplicate Test {uuid.uuid4().hex[:8]}"
|
||||
|
||||
# Create first collection
|
||||
response1 = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": unique_name, "description": "First"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert response1.status_code == 200
|
||||
collection_id = response1.get_json()["collection"]["id"]
|
||||
|
||||
try:
|
||||
# Try to create duplicate
|
||||
response2 = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": unique_name, "description": "Duplicate"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response2.status_code == 400
|
||||
|
||||
data = response2.get_json()
|
||||
assert data["success"] is False
|
||||
assert "exists" in data["error"].lower()
|
||||
finally:
|
||||
# Cleanup
|
||||
delete_test_collection(authenticated_client, collection_id)
|
||||
|
||||
def test_create_collection_without_description(self, authenticated_client):
|
||||
"""Creates collection without description."""
|
||||
unique_name = f"No Desc Collection {uuid.uuid4().hex[:8]}"
|
||||
|
||||
response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": unique_name},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert data["collection"]["name"] == unique_name
|
||||
|
||||
# Cleanup
|
||||
delete_test_collection(authenticated_client, data["collection"]["id"])
|
||||
|
||||
|
||||
class TestUpdateCollection:
|
||||
"""Tests for PUT /library/api/collections/<id> endpoint."""
|
||||
|
||||
def test_update_collection_unauthenticated(self, client):
|
||||
"""Unauthenticated request is rejected."""
|
||||
response = client.put(
|
||||
"/library/api/collections/some-id",
|
||||
json={"name": "Updated"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert response.status_code in [302, 401]
|
||||
|
||||
def test_update_collection_name(
|
||||
self, authenticated_client, create_collection_helper
|
||||
):
|
||||
"""Successfully updates collection name."""
|
||||
created = create_collection_helper(name="Original Name")
|
||||
assert created is not None
|
||||
|
||||
new_name = f"Updated Name {uuid.uuid4().hex[:8]}"
|
||||
response = authenticated_client.put(
|
||||
f"/library/api/collections/{created['id']}",
|
||||
json={"name": new_name},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert data["collection"]["name"] == new_name
|
||||
|
||||
def test_update_collection_description(
|
||||
self, authenticated_client, create_collection_helper
|
||||
):
|
||||
"""Successfully updates collection description."""
|
||||
created = create_collection_helper(description="Original description")
|
||||
assert created is not None
|
||||
|
||||
response = authenticated_client.put(
|
||||
f"/library/api/collections/{created['id']}",
|
||||
json={"description": "Updated description"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
assert data["collection"]["description"] == "Updated description"
|
||||
|
||||
def test_update_collection_not_found(self, authenticated_client):
|
||||
"""Returns 404 for non-existent collection."""
|
||||
fake_id = str(uuid.uuid4())
|
||||
response = authenticated_client.put(
|
||||
f"/library/api/collections/{fake_id}",
|
||||
json={"name": "Updated"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
assert "not found" in data["error"].lower()
|
||||
|
||||
def test_update_collection_duplicate_name(
|
||||
self, authenticated_client, create_collection_helper
|
||||
):
|
||||
"""Rejects update with duplicate name."""
|
||||
# Create two collections
|
||||
coll1 = create_collection_helper(
|
||||
name=f"Collection A {uuid.uuid4().hex[:8]}"
|
||||
)
|
||||
coll2 = create_collection_helper(
|
||||
name=f"Collection B {uuid.uuid4().hex[:8]}"
|
||||
)
|
||||
assert coll1 is not None and coll2 is not None
|
||||
|
||||
# Try to rename coll2 to coll1's name
|
||||
response = authenticated_client.put(
|
||||
f"/library/api/collections/{coll2['id']}",
|
||||
json={"name": coll1["name"]},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
assert "exists" in data["error"].lower()
|
||||
|
||||
|
||||
class TestDeleteCollection:
|
||||
"""Tests for DELETE /library/api/collections/<id> endpoint."""
|
||||
|
||||
def test_delete_collection_unauthenticated(self, client):
|
||||
"""Unauthenticated request is rejected."""
|
||||
response = client.delete("/library/api/collections/some-id")
|
||||
assert response.status_code in [302, 401]
|
||||
|
||||
def test_delete_collection_success(self, authenticated_client):
|
||||
"""Successfully deletes a collection."""
|
||||
# Create a collection to delete
|
||||
unique_name = f"To Delete {uuid.uuid4().hex[:8]}"
|
||||
create_response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": unique_name, "description": "Will be deleted"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert create_response.status_code == 200
|
||||
collection_id = create_response.get_json()["collection"]["id"]
|
||||
|
||||
# Delete it
|
||||
response = authenticated_client.delete(
|
||||
f"/library/api/collections/{collection_id}"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is True
|
||||
|
||||
# Verify it's gone
|
||||
list_response = authenticated_client.get("/library/api/collections")
|
||||
collections = list_response.get_json()["collections"]
|
||||
collection_ids = [c["id"] for c in collections]
|
||||
assert collection_id not in collection_ids
|
||||
|
||||
def test_delete_collection_not_found(self, authenticated_client):
|
||||
"""Returns 404 for non-existent collection."""
|
||||
fake_id = str(uuid.uuid4())
|
||||
response = authenticated_client.delete(
|
||||
f"/library/api/collections/{fake_id}"
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
data = response.get_json()
|
||||
assert data["success"] is False
|
||||
assert "not found" in data["error"].lower()
|
||||
|
||||
|
||||
class TestCollectionIntegration:
|
||||
"""Integration tests for collection workflow."""
|
||||
|
||||
def test_create_read_update_delete_flow(self, authenticated_client):
|
||||
"""Full CRUD workflow."""
|
||||
unique_name = f"CRUD Test {uuid.uuid4().hex[:8]}"
|
||||
|
||||
# Create
|
||||
create_response = authenticated_client.post(
|
||||
"/library/api/collections",
|
||||
json={"name": unique_name, "description": "Initial"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert create_response.status_code == 200
|
||||
collection_id = create_response.get_json()["collection"]["id"]
|
||||
|
||||
try:
|
||||
# Read
|
||||
list_response = authenticated_client.get("/library/api/collections")
|
||||
assert list_response.status_code == 200
|
||||
collections = list_response.get_json()["collections"]
|
||||
our_coll = next(
|
||||
(c for c in collections if c["id"] == collection_id), None
|
||||
)
|
||||
assert our_coll is not None
|
||||
assert our_coll["name"] == unique_name
|
||||
|
||||
# Update
|
||||
updated_name = f"Updated {uuid.uuid4().hex[:8]}"
|
||||
update_response = authenticated_client.put(
|
||||
f"/library/api/collections/{collection_id}",
|
||||
json={"name": updated_name, "description": "Updated desc"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert update_response.status_code == 200
|
||||
|
||||
# Verify update
|
||||
list_response2 = authenticated_client.get(
|
||||
"/library/api/collections"
|
||||
)
|
||||
collections2 = list_response2.get_json()["collections"]
|
||||
our_coll2 = next(
|
||||
(c for c in collections2 if c["id"] == collection_id), None
|
||||
)
|
||||
assert our_coll2["name"] == updated_name
|
||||
assert our_coll2["description"] == "Updated desc"
|
||||
|
||||
finally:
|
||||
# Delete
|
||||
delete_response = authenticated_client.delete(
|
||||
f"/library/api/collections/{collection_id}"
|
||||
)
|
||||
assert delete_response.status_code == 200
|
||||
Reference in New Issue
Block a user