update search/test

This commit is contained in:
2026-03-19 03:39:56 +00:00
parent 42faf7eeb6
commit 5c666382f8
3 changed files with 21 additions and 24 deletions

View File

@@ -122,6 +122,8 @@ public class RecipeController : ControllerBase
[HttpGet("search")] [HttpGet("search")]
public async Task<ActionResult<IEnumerable<Recipe>>> SearchRecipes([FromQuery] string query) public async Task<ActionResult<IEnumerable<Recipe>>> SearchRecipes([FromQuery] string query)
{ {
Console.WriteLine($"--> Search hit! Query: {query}");
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))

View File

@@ -43,7 +43,7 @@
</v-row> </v-row>
<v-row v-else-if="recipes?.length"> <v-row v-else-if="recipes?.length">
<v-col v-for="recipe in sortedRecipes" :key="recipe.id" cols="12" sm="6" md="4"> <v-col v-for="recipe in (searchQuery ? recipes : sortedRecipes)" :key="recipe.id" cols="12" sm="6" md="4">
<v-card class="gallery-item-card pa-4"> <v-card class="gallery-item-card pa-4">
<v-sheet <v-sheet
height="200" height="200"
@@ -53,7 +53,7 @@
> >
<v-img <v-img
v-if="recipe.imageUrl" v-if="recipe.imageUrl"
:src="recipe.imageUrl" :src="recipe.imageUrl.startsWith('http') ? recipe.imageUrl : `${config.public.apiBase}${recipe.imageUrl}`"
cover cover
class="recipe-thumbnail" class="recipe-thumbnail"
></v-img> ></v-img>
@@ -134,7 +134,7 @@
> >
<v-img <v-img
v-if="selectedRecipe.imageUrl" v-if="selectedRecipe.imageUrl"
:src="selectedRecipe.imageUrl" :src="selectedRecipe.imageUrl.startsWith('http') ? selectedRecipe.imageUrl : `${config.public.apiBase}${selectedRecipe.imageUrl}`"
cover cover
class="rounded-lg fill-height" class="rounded-lg fill-height"
></v-img> ></v-img>
@@ -435,12 +435,13 @@ const performSearch = async () => {
try { try {
isSearching.value = true isSearching.value = true
const data = await $fetch(`${config.public.apiBase}api/recipe/search`, { const data = await $fetch(`${config.public.apiBase}api/recipe/search`, {
params: { query: searchQuery.value }, query: { query: searchQuery.value },
credentials: 'include' credentials: 'include'
}) })
console.log("Search results received:", data)
recipes.value = data recipes.value = data
} catch (err) { } catch (err) {
console.error("The Chef couldn't find those flavors:", err) console.error("Search failed:", err)
} finally { } finally {
isSearching.value = false isSearching.value = false
} }

View File

@@ -47,7 +47,6 @@ describe('GalleryPage.vue', () => {
} }
it('shows loading state initially and then renders recipes', async () => { it('shows loading state initially and then renders recipes', async () => {
mockFetch.mockResolvedValueOnce([ mockFetch.mockResolvedValueOnce([
{ id: 1, title: 'Bolognese', createdAt: new Date().toISOString(), ingredients: [], instructions: [] } { id: 1, title: 'Bolognese', createdAt: new Date().toISOString(), ingredients: [], instructions: [] }
]) ])
@@ -63,7 +62,8 @@ describe('GalleryPage.vue', () => {
it('triggers semantic search when searchQuery changes', async () => { it('triggers semantic search when searchQuery changes', async () => {
vi.useFakeTimers() vi.useFakeTimers()
mockFetch.mockResolvedValue([])
mockFetch.mockResolvedValueOnce([])
const wrapper = mount(GalleryPage, mountOptions) const wrapper = mount(GalleryPage, mountOptions)
@@ -79,14 +79,15 @@ describe('GalleryPage.vue', () => {
await flushPromises() await flushPromises()
expect(mockFetch).toHaveBeenCalledWith( expect(mockFetch).toHaveBeenCalledWith(
expect.stringContaining('api/recipe/search'), expect.stringContaining('api/recipe/search'),
expect.objectContaining({ expect.objectContaining({
params: expect.objectContaining({ query: 'spicy pasta' }) query: { query: 'spicy pasta' },
}) credentials: 'include'
})
) )
vi.useRealTimers() vi.useRealTimers()
}) })
it('redirects to login if API returns 401', async () => { it('redirects to login if API returns 401', async () => {
mockFetch.mockReset() mockFetch.mockReset()
@@ -99,7 +100,7 @@ describe('GalleryPage.vue', () => {
await vi.waitFor(() => { await vi.waitFor(() => {
expect(mockNavigate).toHaveBeenCalledWith('/login') expect(mockNavigate).toHaveBeenCalledWith('/login')
}, { timeout: 1000 }) }, { timeout: 1000 })
}) })
it('enters editing mode and formats arrays into strings', async () => { it('enters editing mode and formats arrays into strings', async () => {
mockFetch.mockResolvedValueOnce([ mockFetch.mockResolvedValueOnce([
@@ -139,18 +140,11 @@ describe('GalleryPage.vue', () => {
expect(mockFetch).toHaveBeenCalledWith( expect(mockFetch).toHaveBeenCalledWith(
expect.stringContaining('api/recipe/update/1'), expect.stringContaining('api/recipe/update/1'),
expect.objectContaining({ method: 'PUT' }) expect.objectContaining({
method: 'PUT',
credentials: 'include'
})
) )
expect(vm.recipes[0].title).toBe('New Title') expect(vm.recipes[0].title).toBe('New Title')
}) })
it('redirects to login if API returns 401', async () => {
mockFetch.mockRejectedValueOnce({ status: 401 })
mount(GalleryPage, mountOptions)
await vi.waitFor(() => {
expect(mockNavigate).toHaveBeenCalledWith('/login')
})
})
}) })