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:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user