refactor: update to Qdrant query_points API and fix Playwright Keycloak login

- Replace deprecated qdrant_client.search() with query_points() API
- Update semantic search implementation in notes.py
- Update all integration tests to use query_points()
- Fix Keycloak login in test_keycloak_dcr.py to use form.submit() instead of button click
- Remove unnecessary popup handler code
- Simplify consent screen logging
This commit is contained in:
Chris Coutinho
2025-11-08 22:41:14 +01:00
parent e96c02e4d4
commit 1a57f97d3a
3 changed files with 33 additions and 31 deletions
+3 -3
View File
@@ -414,9 +414,9 @@ def configure_notes_tools(mcp: FastMCP):
# Search Qdrant with user filtering
qdrant_client = await get_qdrant_client()
search_results = await qdrant_client.search(
search_response = await qdrant_client.query_points(
collection_name=settings.qdrant_collection,
query_vector=query_embedding,
query=query_embedding,
query_filter=Filter(
must=[
FieldCondition(
@@ -439,7 +439,7 @@ def configure_notes_tools(mcp: FastMCP):
seen_note_ids = set()
results = []
for result in search_results:
for result in search_response.points:
note_id = int(result.payload["doc_id"])
# Skip if we've already seen this note
+20 -20
View File
@@ -207,32 +207,32 @@ async def test_semantic_search_with_qdrant(
query = "async programming patterns in Python"
query_embedding = await simple_embedding_provider.embed(query)
results = await qdrant_test_client.search(
response = await qdrant_test_client.query_points(
collection_name=test_collection,
query_vector=query_embedding,
query=query_embedding,
limit=3,
score_threshold=0.0,
)
# Should find Python note as top result
assert len(results) > 0
assert results[0].payload["note_id"] == 1
assert "Python" in results[0].payload["title"]
assert len(response.points) > 0
assert response.points[0].payload["note_id"] == 1
assert "Python" in response.points[0].payload["title"]
# Test Query 2: Search for books
query = "good books to read recommendations"
query_embedding = await simple_embedding_provider.embed(query)
results = await qdrant_test_client.search(
response = await qdrant_test_client.query_points(
collection_name=test_collection,
query_vector=query_embedding,
query=query_embedding,
limit=3,
score_threshold=0.0,
)
# Should find book recommendations note
assert len(results) > 0
top_result = results[0]
assert len(response.points) > 0
top_result = response.points[0]
assert top_result.payload["note_id"] == 2
assert "Book" in top_result.payload["title"]
@@ -240,17 +240,17 @@ async def test_semantic_search_with_qdrant(
query = "how to bake cookies dessert"
query_embedding = await simple_embedding_provider.embed(query)
results = await qdrant_test_client.search(
response = await qdrant_test_client.query_points(
collection_name=test_collection,
query_vector=query_embedding,
query=query_embedding,
limit=3,
score_threshold=0.0,
)
# Should find recipe note
assert len(results) > 0
assert len(response.points) > 0
# Recipe should be in top 2 results
top_note_ids = [r.payload["note_id"] for r in results[:2]]
top_note_ids = [r.payload["note_id"] for r in response.points[:2]]
assert 3 in top_note_ids
@@ -289,9 +289,9 @@ async def test_semantic_search_with_filters(
query = "books reading"
query_embedding = await simple_embedding_provider.embed(query)
results = await qdrant_test_client.search(
response = await qdrant_test_client.query_points(
collection_name=test_collection,
query_vector=query_embedding,
query=query_embedding,
query_filter=Filter(
must=[FieldCondition(key="category", match=MatchValue(value="Personal"))]
),
@@ -299,8 +299,8 @@ async def test_semantic_search_with_filters(
)
# Should only return Personal category notes
assert len(results) > 0
for result in results:
assert len(response.points) > 0
for result in response.points:
assert result.payload["category"] == "Personal"
@@ -314,13 +314,13 @@ async def test_semantic_search_empty_results(
query = "test query"
query_embedding = await simple_embedding_provider.embed(query)
results = await qdrant_test_client.search(
response = await qdrant_test_client.query_points(
collection_name=test_collection,
query_vector=query_embedding,
query=query_embedding,
limit=10,
)
assert len(results) == 0
assert len(response.points) == 0
async def test_batch_embedding(simple_embedding_provider: SimpleEmbeddingProvider):
+10 -8
View File
@@ -46,9 +46,10 @@ async def handle_keycloak_login(page, username: str, password: str):
Keycloak uses:
- input#username for username field
- input#password for password field
- input[type="submit"] for submit button
- Form submission via JavaScript (more reliable than clicking button)
"""
logger.info(f"Handling Keycloak login for user: {username}")
logger.info(f"Current URL before login: {page.url}")
# Wait for username field and fill it
await page.wait_for_selector("input#username", timeout=10000)
@@ -58,11 +59,12 @@ async def handle_keycloak_login(page, username: str, password: str):
await page.wait_for_selector("input#password", timeout=10000)
await page.fill("input#password", password)
# Click submit button
await page.click('input[type="submit"]')
await page.wait_for_load_state("networkidle", timeout=60000)
# Submit form using JavaScript (more reliable than clicking button)
logger.info("Submitting Keycloak login form...")
async with page.expect_navigation(timeout=60000):
await page.evaluate("document.querySelector('form').submit()")
logger.info("✓ Keycloak login completed")
logger.info(f"✓ Keycloak login completed, redirected to: {page.url}")
async def handle_keycloak_consent(page, client_name: str):
@@ -80,9 +82,9 @@ async def handle_keycloak_consent(page, client_name: str):
# Wait for consent screen (button with name="accept")
await page.wait_for_selector('button[name="accept"]', timeout=5000)
# Click accept button
await page.click('button[name="accept"]')
await page.wait_for_load_state("networkidle", timeout=60000)
# Click accept button and wait for navigation
async with page.expect_navigation(timeout=60000):
await page.click('button[name="accept"]')
logger.info("✓ Keycloak consent granted")
except Exception as e: