mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-18 10:14:24 +00:00
Pg 4 (#2390)
* feat: postgres tests * feat: mongo cutoff * feat: mongo cutoff * feat: adjust docs and compose files * fix: mini code mongo removals * fix: tests and k8s mongo stuff * feat: test fixes * fix: ruff * fix: vale * Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fix: mini suggestions * vale lint fix 2 * fix: codeql columns thing * fix: test mongo * fix: tests coverage * feat: better tests 4 * feat: more tests * feat: decent coverage * fix: ruff fixes * fix: remove mongo mock * feat: enhance workflow engine and API routes; add document retrieval and source handling * feat: e2e tests * fix: mcp, mongo and more * fix: mini codeql warning * fix: agent chunk view * fix: mini issues * fix: more pg fixes * feat: postgres prep on start * feat: qa tests * fix: mini improvements * fix: tests --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Siddhant Rai <siddhant.rai.5686@gmail.com>
This commit is contained in:
312 files changed
+763725
-25159
No files matched your search
+413
-172
@@ -1,7 +1,8 @@
|
||||
from unittest.mock import Mock, mock_open, patch
|
||||
import uuid
|
||||
from contextlib import contextmanager
|
||||
from unittest.mock import mock_open, patch
|
||||
|
||||
import pytest
|
||||
from bson import ObjectId
|
||||
from flask import Flask
|
||||
|
||||
|
||||
@@ -11,49 +12,24 @@ def app():
|
||||
return app
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _patch_db(conn):
|
||||
"""Patch both db_session and db_readonly to yield the given conn."""
|
||||
@contextmanager
|
||||
def _yield_conn():
|
||||
yield conn
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.db_session", _yield_conn
|
||||
), patch(
|
||||
"application.api.user.prompts.routes.db_readonly", _yield_conn
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestCreatePrompt:
|
||||
|
||||
def test_creates_prompt(self, app):
|
||||
from application.api.user.prompts.routes import CreatePrompt
|
||||
|
||||
mock_collection = Mock()
|
||||
mock_repo = Mock()
|
||||
inserted_id = ObjectId()
|
||||
mock_collection.insert_one.return_value = Mock(inserted_id=inserted_id)
|
||||
|
||||
def _run_dual_write(_repo_cls, fn):
|
||||
fn(mock_repo)
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.prompts_collection",
|
||||
mock_collection,
|
||||
), patch(
|
||||
"application.api.user.prompts.routes.dual_write",
|
||||
side_effect=_run_dual_write,
|
||||
):
|
||||
with app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "My Prompt", "content": "You are helpful."},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user1"}
|
||||
response = CreatePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["id"] == str(inserted_id)
|
||||
mock_collection.insert_one.assert_called_once()
|
||||
doc = mock_collection.insert_one.call_args[0][0]
|
||||
assert doc["name"] == "My Prompt"
|
||||
assert doc["user"] == "user1"
|
||||
mock_repo.create.assert_called_once_with(
|
||||
"user1",
|
||||
"My Prompt",
|
||||
"You are helpful.",
|
||||
legacy_mongo_id=str(inserted_id),
|
||||
)
|
||||
pass
|
||||
|
||||
def test_returns_401_unauthenticated(self, app):
|
||||
from application.api.user.prompts.routes import CreatePrompt
|
||||
@@ -88,35 +64,7 @@ class TestCreatePrompt:
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestGetPrompts:
|
||||
|
||||
def test_returns_prompts_with_defaults(self, app):
|
||||
from application.api.user.prompts.routes import GetPrompts
|
||||
|
||||
user_prompt_id = ObjectId()
|
||||
mock_collection = Mock()
|
||||
mock_collection.find.return_value = [
|
||||
{"_id": user_prompt_id, "name": "Custom Prompt"}
|
||||
]
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.prompts_collection",
|
||||
mock_collection,
|
||||
):
|
||||
with app.test_request_context("/api/get_prompts"):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user1"}
|
||||
response = GetPrompts().get()
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json
|
||||
public_names = [p["name"] for p in data if p["type"] == "public"]
|
||||
assert "default" in public_names
|
||||
assert "creative" in public_names
|
||||
assert "strict" in public_names
|
||||
private = [p for p in data if p["type"] == "private"]
|
||||
assert len(private) == 1
|
||||
assert private[0]["name"] == "Custom Prompt"
|
||||
pass
|
||||
|
||||
def test_returns_401_unauthenticated(self, app):
|
||||
from application.api.user.prompts.routes import GetPrompts
|
||||
@@ -132,6 +80,7 @@ class TestGetPrompts:
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestGetSinglePrompt:
|
||||
pass
|
||||
|
||||
def test_returns_default_prompt(self, app):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
@@ -172,30 +121,6 @@ class TestGetSinglePrompt:
|
||||
assert response.status_code == 200
|
||||
assert response.json["content"] == "Strict content"
|
||||
|
||||
def test_returns_custom_prompt(self, app):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
|
||||
prompt_id = ObjectId()
|
||||
mock_collection = Mock()
|
||||
mock_collection.find_one.return_value = {
|
||||
"_id": prompt_id,
|
||||
"content": "Custom content",
|
||||
}
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.prompts_collection",
|
||||
mock_collection,
|
||||
):
|
||||
with app.test_request_context(
|
||||
f"/api/get_single_prompt?id={prompt_id}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user1"}
|
||||
response = GetSinglePrompt().get()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["content"] == "Custom content"
|
||||
|
||||
def test_returns_400_missing_id(self, app):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
@@ -211,40 +136,7 @@ class TestGetSinglePrompt:
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestDeletePrompt:
|
||||
|
||||
def test_deletes_prompt(self, app):
|
||||
from application.api.user.prompts.routes import DeletePrompt
|
||||
|
||||
prompt_id = ObjectId()
|
||||
mock_collection = Mock()
|
||||
mock_repo = Mock()
|
||||
|
||||
def _run_dual_write(_repo_cls, fn):
|
||||
fn(mock_repo)
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.prompts_collection",
|
||||
mock_collection,
|
||||
), patch(
|
||||
"application.api.user.prompts.routes.dual_write",
|
||||
side_effect=_run_dual_write,
|
||||
):
|
||||
with app.test_request_context(
|
||||
"/api/delete_prompt",
|
||||
method="POST",
|
||||
json={"id": str(prompt_id)},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user1"}
|
||||
response = DeletePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["success"] is True
|
||||
mock_collection.delete_one.assert_called_once_with(
|
||||
{"_id": prompt_id, "user": "user1"}
|
||||
)
|
||||
mock_repo.delete_by_legacy_id.assert_called_once_with(str(prompt_id), "user1")
|
||||
pass
|
||||
|
||||
def test_returns_400_missing_id(self, app):
|
||||
from application.api.user.prompts.routes import DeletePrompt
|
||||
@@ -264,47 +156,7 @@ class TestDeletePrompt:
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestUpdatePrompt:
|
||||
|
||||
def test_updates_prompt(self, app):
|
||||
from application.api.user.prompts.routes import UpdatePrompt
|
||||
|
||||
prompt_id = ObjectId()
|
||||
mock_collection = Mock()
|
||||
mock_repo = Mock()
|
||||
|
||||
def _run_dual_write(_repo_cls, fn):
|
||||
fn(mock_repo)
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.prompts_collection",
|
||||
mock_collection,
|
||||
), patch(
|
||||
"application.api.user.prompts.routes.dual_write",
|
||||
side_effect=_run_dual_write,
|
||||
):
|
||||
with app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={
|
||||
"id": str(prompt_id),
|
||||
"name": "Updated",
|
||||
"content": "New content",
|
||||
},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user1"}
|
||||
response = UpdatePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["success"] is True
|
||||
mock_collection.update_one.assert_called_once()
|
||||
mock_repo.update_by_legacy_id.assert_called_once_with(
|
||||
str(prompt_id),
|
||||
"user1",
|
||||
"Updated",
|
||||
"New content",
|
||||
)
|
||||
pass
|
||||
|
||||
def test_returns_400_missing_fields(self, app):
|
||||
from application.api.user.prompts.routes import UpdatePrompt
|
||||
@@ -312,7 +164,7 @@ class TestUpdatePrompt:
|
||||
with app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={"id": str(ObjectId()), "name": "Updated"},
|
||||
json={"id": str(uuid.uuid4().hex[:24]), "name": "Updated"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
@@ -320,3 +172,392 @@ class TestUpdatePrompt:
|
||||
response = UpdatePrompt().post()
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Happy-path tests using the ephemeral pg_conn fixture
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestCreatePromptHappyPath:
|
||||
def test_creates_prompt_returns_id(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import CreatePrompt
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "P1", "content": "c1"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "user-create"}
|
||||
response = CreatePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "id" in response.json
|
||||
|
||||
def test_create_error_returns_400(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import CreatePrompt
|
||||
|
||||
# Force repository error by closing the connection first
|
||||
@contextmanager
|
||||
def _broken():
|
||||
raise RuntimeError("simulated db error")
|
||||
yield # unreachable
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.db_session", _broken
|
||||
), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "P", "content": "c"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "u1"}
|
||||
response = CreatePrompt().post()
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
class TestGetPromptsHappyPath:
|
||||
def test_returns_builtin_plus_user_prompts(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import CreatePrompt, GetPrompts
|
||||
|
||||
user = "user-list"
|
||||
# Seed two prompts via the same endpoint
|
||||
for name in ("alpha", "beta"):
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": name, "content": f"content-{name}"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
CreatePrompt().post()
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context("/api/get_prompts"):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = GetPrompts().get()
|
||||
|
||||
assert response.status_code == 200
|
||||
names = [p["name"] for p in response.json]
|
||||
# Three built-ins always present
|
||||
assert "default" in names and "creative" in names and "strict" in names
|
||||
assert "alpha" in names and "beta" in names
|
||||
|
||||
def test_get_error_returns_400(self, app):
|
||||
from application.api.user.prompts.routes import GetPrompts
|
||||
|
||||
@contextmanager
|
||||
def _broken():
|
||||
raise RuntimeError("simulated db error")
|
||||
yield
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.db_readonly", _broken
|
||||
), app.test_request_context("/api/get_prompts"):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "u1"}
|
||||
response = GetPrompts().get()
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
class TestGetSinglePromptHappyPath:
|
||||
def test_returns_private_prompt_content(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import (
|
||||
CreatePrompt,
|
||||
GetSinglePrompt,
|
||||
)
|
||||
|
||||
user = "user-get1"
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "custom", "content": "hello world"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
created = CreatePrompt().post()
|
||||
prompt_id = created.json["id"]
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
f"/api/get_single_prompt?id={prompt_id}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = GetSinglePrompt().get()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["content"] == "hello world"
|
||||
|
||||
def test_returns_404_for_unknown_prompt(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
|
||||
bogus_id = str(uuid.uuid4())
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
f"/api/get_single_prompt?id={bogus_id}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "whoever"}
|
||||
response = GetSinglePrompt().get()
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_file_read_exception_returns_400(self, app):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
|
||||
with patch("builtins.open", side_effect=OSError("boom")), \
|
||||
app.test_request_context("/api/get_single_prompt?id=default"):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "u1"}
|
||||
response = GetSinglePrompt().get()
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
class TestDeletePromptHappyPath:
|
||||
def test_deletes_existing_prompt(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import (
|
||||
CreatePrompt,
|
||||
DeletePrompt,
|
||||
GetSinglePrompt,
|
||||
)
|
||||
|
||||
user = "user-del"
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "to-delete", "content": "bye"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
created = CreatePrompt().post()
|
||||
prompt_id = created.json["id"]
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/delete_prompt",
|
||||
method="POST",
|
||||
json={"id": prompt_id},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = DeletePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["success"] is True
|
||||
|
||||
# Verify gone
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
f"/api/get_single_prompt?id={prompt_id}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
check = GetSinglePrompt().get()
|
||||
assert check.status_code == 404
|
||||
|
||||
def test_delete_returns_401_unauthenticated(self, app):
|
||||
from application.api.user.prompts.routes import DeletePrompt
|
||||
|
||||
with app.test_request_context(
|
||||
"/api/delete_prompt",
|
||||
method="POST",
|
||||
json={"id": "something"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = None
|
||||
response = DeletePrompt().post()
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_delete_error_returns_400(self, app):
|
||||
from application.api.user.prompts.routes import DeletePrompt
|
||||
|
||||
@contextmanager
|
||||
def _broken():
|
||||
raise RuntimeError("boom")
|
||||
yield
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.db_session", _broken
|
||||
), app.test_request_context(
|
||||
"/api/delete_prompt",
|
||||
method="POST",
|
||||
json={"id": "pid"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "u1"}
|
||||
response = DeletePrompt().post()
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
class TestLegacyMongoIdResolution:
|
||||
"""Pre-cutover prompt ids (Mongo ObjectIds) must resolve on all three
|
||||
mutating endpoints once the prompts.legacy_mongo_id column is populated
|
||||
by backfill. Previously the route short-circuited on non-UUID input via
|
||||
``CAST(:id AS uuid)`` which raised and poisoned the transaction."""
|
||||
|
||||
LEGACY_ID = "507f1f77bcf86cd799439011"
|
||||
|
||||
def _seed_legacy(self, pg_conn, user: str, name: str, content: str):
|
||||
from application.storage.db.repositories.prompts import PromptsRepository
|
||||
|
||||
return PromptsRepository(pg_conn).create(
|
||||
user, name, content, legacy_mongo_id=self.LEGACY_ID,
|
||||
)
|
||||
|
||||
def test_get_single_prompt_resolves_legacy_id(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import GetSinglePrompt
|
||||
|
||||
user = "legacy-user"
|
||||
self._seed_legacy(pg_conn, user, "orig", "legacy-body")
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
f"/api/get_single_prompt?id={self.LEGACY_ID}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = GetSinglePrompt().get()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["content"] == "legacy-body"
|
||||
|
||||
def test_delete_prompt_resolves_legacy_id(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import DeletePrompt
|
||||
from application.storage.db.repositories.prompts import PromptsRepository
|
||||
|
||||
user = "legacy-user-del"
|
||||
self._seed_legacy(pg_conn, user, "to-delete", "x")
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/delete_prompt",
|
||||
method="POST",
|
||||
json={"id": self.LEGACY_ID},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = DeletePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json["success"] is True
|
||||
assert PromptsRepository(pg_conn).get_by_legacy_id(
|
||||
self.LEGACY_ID, user,
|
||||
) is None
|
||||
|
||||
def test_update_prompt_resolves_legacy_id(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import UpdatePrompt
|
||||
from application.storage.db.repositories.prompts import PromptsRepository
|
||||
|
||||
user = "legacy-user-upd"
|
||||
self._seed_legacy(pg_conn, user, "old-name", "old-content")
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={"id": self.LEGACY_ID, "name": "new-name", "content": "new-content"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = UpdatePrompt().post()
|
||||
|
||||
assert response.status_code == 200
|
||||
fetched = PromptsRepository(pg_conn).get_by_legacy_id(self.LEGACY_ID, user)
|
||||
assert fetched["name"] == "new-name"
|
||||
assert fetched["content"] == "new-content"
|
||||
|
||||
|
||||
class TestUpdatePromptHappyPath:
|
||||
def test_updates_prompt(self, app, pg_conn):
|
||||
from application.api.user.prompts.routes import (
|
||||
CreatePrompt,
|
||||
GetSinglePrompt,
|
||||
UpdatePrompt,
|
||||
)
|
||||
|
||||
user = "user-upd"
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/create_prompt",
|
||||
method="POST",
|
||||
json={"name": "orig", "content": "v1"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
created = CreatePrompt().post()
|
||||
prompt_id = created.json["id"]
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={"id": prompt_id, "name": "renamed", "content": "v2"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
response = UpdatePrompt().post()
|
||||
assert response.status_code == 200
|
||||
|
||||
with _patch_db(pg_conn), app.test_request_context(
|
||||
f"/api/get_single_prompt?id={prompt_id}"
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": user}
|
||||
check = GetSinglePrompt().get()
|
||||
assert check.status_code == 200
|
||||
assert check.json["content"] == "v2"
|
||||
|
||||
def test_update_returns_401_unauthenticated(self, app):
|
||||
from application.api.user.prompts.routes import UpdatePrompt
|
||||
|
||||
with app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={"id": "x", "name": "n", "content": "c"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = None
|
||||
response = UpdatePrompt().post()
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_update_error_returns_400(self, app):
|
||||
from application.api.user.prompts.routes import UpdatePrompt
|
||||
|
||||
@contextmanager
|
||||
def _broken():
|
||||
raise RuntimeError("boom")
|
||||
yield
|
||||
|
||||
with patch(
|
||||
"application.api.user.prompts.routes.db_session", _broken
|
||||
), app.test_request_context(
|
||||
"/api/update_prompt",
|
||||
method="POST",
|
||||
json={"id": "x", "name": "n", "content": "c"},
|
||||
):
|
||||
from flask import request
|
||||
|
||||
request.decoded_token = {"sub": "u1"}
|
||||
response = UpdatePrompt().post()
|
||||
|
||||
assert response.status_code == 400
|
||||
Reference in new issue
Block a user