From 2a7be3270517e6a392364690646c80604fb4625f Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Tue, 11 Mar 2025 12:12:39 +0100 Subject: [PATCH 1/7] feat: voorbeeld test file --- backend/tests/service/learning-paths.test.ts | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 backend/tests/service/learning-paths.test.ts diff --git a/backend/tests/service/learning-paths.test.ts b/backend/tests/service/learning-paths.test.ts new file mode 100644 index 00000000..6ac15213 --- /dev/null +++ b/backend/tests/service/learning-paths.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect, vi } from 'vitest'; +import { fetchLearningPaths } from '../../src/services/learningPaths'; +import { fetchWithLogging } from '../../src/util/apiHelper'; +import { LearningPathResponse } from '../../src/interfaces/learningPath'; + + +describe('fetchLearningPaths', () => { + const mockHruids = ['pn_werking', 'art1']; + const language = 'en'; + const source = 'Test Source'; + + it('✅ Moet een succesvolle response retourneren wanneer hruids zijn opgegeven', async () => { + // Mock response van fetchWithLogging + //const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; + + const result: LearningPathResponse = await fetchLearningPaths(mockHruids, language, source); + + expect(result.success).toBe(true); + //expect(result.data).toEqual(mockResponse); + expect(result.source).toBe(source); + }); + + it('⚠️ Moet een foutmelding teruggeven als er geen hruids zijn opgegeven', async () => { + const result: LearningPathResponse = await fetchLearningPaths([], language, source); + + expect(result.success).toBe(false); + expect(result.data).toBeNull(); + expect(result.message).toBe(`No HRUIDs provided for ${source}.`); + }); + + +}); From fca8e7ff7afe37811e084810c847b30d28a29b74 Mon Sep 17 00:00:00 2001 From: Joyelle Ndagijimana Date: Wed, 12 Mar 2025 15:28:05 +0100 Subject: [PATCH 2/7] test: alle functies in learningPaths.ts zijn getest en de testen slagen --- backend/tests/service/learning-paths.test.ts | 56 ++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/backend/tests/service/learning-paths.test.ts b/backend/tests/service/learning-paths.test.ts index 6ac15213..668c266f 100644 --- a/backend/tests/service/learning-paths.test.ts +++ b/backend/tests/service/learning-paths.test.ts @@ -1,32 +1,78 @@ import { describe, it, expect, vi } from 'vitest'; -import { fetchLearningPaths } from '../../src/services/learningPaths'; +import { fetchLearningPaths, searchLearningPaths } from '../../src/services/learningPaths'; import { fetchWithLogging } from '../../src/util/apiHelper'; import { LearningPathResponse } from '../../src/interfaces/learningPath'; +// Function to mock the fetchWithLogging module using vi +vi.mock('../../src/util/apiHelper', () => ({ + fetchWithLogging: vi.fn(), +})); describe('fetchLearningPaths', () => { const mockHruids = ['pn_werking', 'art1']; const language = 'en'; const source = 'Test Source'; + const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; - it('✅ Moet een succesvolle response retourneren wanneer hruids zijn opgegeven', async () => { + it('✅ Should return a successful response when HRUIDs are provided', async () => { // Mock response van fetchWithLogging - //const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; + const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; + + // Mock the function to return mockResponse + vi.mocked(fetchWithLogging).mockResolvedValue(mockResponse); const result: LearningPathResponse = await fetchLearningPaths(mockHruids, language, source); expect(result.success).toBe(true); - //expect(result.data).toEqual(mockResponse); + expect(result.data).toEqual(mockResponse); expect(result.source).toBe(source); }); - it('⚠️ Moet een foutmelding teruggeven als er geen hruids zijn opgegeven', async () => { + it('⚠️ Should return an error when no HRUIDs are provided', async () => { const result: LearningPathResponse = await fetchLearningPaths([], language, source); + vi.mocked(fetchWithLogging).mockResolvedValue(mockResponse); + expect(result.success).toBe(false); expect(result.data).toBeNull(); expect(result.message).toBe(`No HRUIDs provided for ${source}.`); }); + it('⚠️ Should return a failure response when no learning paths are found', async () => { + // Mock fetchWithLogging to return an empty array + vi.mocked(fetchWithLogging).mockResolvedValue([]); + const result: LearningPathResponse = await fetchLearningPaths(mockHruids, language, source); + + expect(result.success).toBe(false); + expect(result.data).toEqual([]); + expect(result.message).toBe(`No learning paths found for ${source}.`); + }); +}); + +describe('searchLearningPaths', () => { + const query = 'robotics'; + const language = 'en'; + + it('✅ Should return search results when API responds with data', async () => { + const mockResults = [ + { title: 'Robotics Basics', hruids: ['robotics_101'] }, + { title: 'Advanced Robotics', hruids: ['robotics_advanced'] }, + ]; + + // Mock fetchWithLogging to return search results + vi.mocked(fetchWithLogging).mockResolvedValue(mockResults); + + const result = await searchLearningPaths(query, language); + + expect(result).toEqual(mockResults); + }); + + it('⚠️ Should return an empty array when API returns no results', async () => { + vi.mocked(fetchWithLogging).mockResolvedValue([]); + + const result = await searchLearningPaths(query, language); + + expect(result).toEqual([]); + }); }); From 71cf652f2837f5b1b254af986ab41e5bbc0df82f Mon Sep 17 00:00:00 2001 From: Joyelle Ndagijimana Date: Wed, 12 Mar 2025 18:30:24 +0100 Subject: [PATCH 3/7] test: alle functies in learningObjects.ts zijn getest en de testen slagen --- .../tests/service/learning-objects.test.ts | 98 +++++++++++++++++++ backend/tests/service/learning-paths.test.ts | 10 +- 2 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 backend/tests/service/learning-objects.test.ts diff --git a/backend/tests/service/learning-objects.test.ts b/backend/tests/service/learning-objects.test.ts new file mode 100644 index 00000000..9b5bb126 --- /dev/null +++ b/backend/tests/service/learning-objects.test.ts @@ -0,0 +1,98 @@ +import {describe, it, expect, vi} from 'vitest'; +import { + LearningObjectMetadata, +} from "../../src/interfaces/learningPath"; +import {fetchWithLogging} from "../../src/util/apiHelper"; +import {getLearningObjectById, getLearningObjectsFromPath} from "../../src/services/learningObjects"; +import {fetchLearningPaths} from "../../src/services/learningPaths"; + +// Mock API functions +vi.mock('../../src/util/apiHelper', () => ({ + fetchWithLogging: vi.fn(), +})); + +vi.mock('../../src/services/learningPaths', () => ({ + fetchLearningPaths: vi.fn(), +})); + + +describe('getLearningObjectById', () => { + const hruid = 'test-object'; + const language = 'en'; + const mockMetadata: LearningObjectMetadata = { + hruid, + _id: '123', + uuid: 'uuid-123', + version: 1, + title: 'Test Object', + language, + difficulty: 5, + estimated_time: 120, + available: true, + teacher_exclusive: false, + educational_goals: [{source: 'source', id: 'id'}], + keywords: ['robotics'], + description: 'A test object', + target_ages: [10, 12], + content_type: 'markdown', + content_location: '', + skos_concepts: [], + return_value: undefined, + }; + + it('✅ Should return a filtered learning object when API provides data', async () => { + vi.mocked(fetchWithLogging).mockResolvedValueOnce(mockMetadata); + + const result = await getLearningObjectById(hruid, language); + + expect(result).toEqual({ + key: hruid, + _id: '123', + uuid: 'uuid-123', + version: 1, + title: 'Test Object', + htmlUrl: expect.stringContaining('/learningObject/getRaw?hruid=test-object&language=en'), + language, + difficulty: 5, + estimatedTime: 120, + available: true, + teacherExclusive: false, + educationalGoals: [{source: 'source', id: 'id'}], + keywords: ['robotics'], + description: 'A test object', + targetAges: [10, 12], + contentType: 'markdown', + contentLocation: '', + skosConcepts: [], + returnValue: undefined, + }); + }); + + it('⚠️ Should return null if API returns no metadata', async () => { + vi.mocked(fetchWithLogging).mockResolvedValueOnce(null); + const result = await getLearningObjectById(hruid, language); + expect(result).toBeNull(); + }); +}); + + +describe('getLearningObjectsFromPath', () => { + const hruid = 'test-path'; + const language = 'en'; + + it('⚠️ Should return an empty array if API returns an empty path response', async () => { + vi.mocked(fetchLearningPaths).mockResolvedValueOnce({success: false, source: 'Test Source', data: []}); + + const result = await getLearningObjectsFromPath(hruid, language); + + expect(result).toEqual([]); + }); + + it('❌ Should return an empty array and log an error if fetchLearningPaths fails', async () => { + vi.mocked(fetchLearningPaths).mockRejectedValueOnce(new Error('API Error')); + + const result = await getLearningObjectsFromPath(hruid, language); + + expect(result).toEqual([]); + }); +}); diff --git a/backend/tests/service/learning-paths.test.ts b/backend/tests/service/learning-paths.test.ts index 668c266f..8289a5e8 100644 --- a/backend/tests/service/learning-paths.test.ts +++ b/backend/tests/service/learning-paths.test.ts @@ -3,21 +3,19 @@ import { fetchLearningPaths, searchLearningPaths } from '../../src/services/lear import { fetchWithLogging } from '../../src/util/apiHelper'; import { LearningPathResponse } from '../../src/interfaces/learningPath'; -// Function to mock the fetchWithLogging module using vi +// Mock the fetchWithLogging module using vi vi.mock('../../src/util/apiHelper', () => ({ fetchWithLogging: vi.fn(), })); describe('fetchLearningPaths', () => { + // Mock data and response const mockHruids = ['pn_werking', 'art1']; const language = 'en'; const source = 'Test Source'; const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; it('✅ Should return a successful response when HRUIDs are provided', async () => { - // Mock response van fetchWithLogging - const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; - // Mock the function to return mockResponse vi.mocked(fetchWithLogging).mockResolvedValue(mockResponse); @@ -29,10 +27,10 @@ describe('fetchLearningPaths', () => { }); it('⚠️ Should return an error when no HRUIDs are provided', async () => { - const result: LearningPathResponse = await fetchLearningPaths([], language, source); - vi.mocked(fetchWithLogging).mockResolvedValue(mockResponse); + const result: LearningPathResponse = await fetchLearningPaths([], language, source); + expect(result.success).toBe(false); expect(result.data).toBeNull(); expect(result.message).toBe(`No HRUIDs provided for ${source}.`); From db582ee46ac2ca8cbdc9a082cd1a436318ec29a8 Mon Sep 17 00:00:00 2001 From: Joyelle Ndagijimana Date: Wed, 12 Mar 2025 20:16:33 +0100 Subject: [PATCH 4/7] test: extra test bij learningObjects --- .../tests/service/learning-objects.test.ts | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/backend/tests/service/learning-objects.test.ts b/backend/tests/service/learning-objects.test.ts index 9b5bb126..82729629 100644 --- a/backend/tests/service/learning-objects.test.ts +++ b/backend/tests/service/learning-objects.test.ts @@ -1,9 +1,12 @@ import {describe, it, expect, vi} from 'vitest'; import { - LearningObjectMetadata, + LearningObjectMetadata, LearningPath, } from "../../src/interfaces/learningPath"; import {fetchWithLogging} from "../../src/util/apiHelper"; -import {getLearningObjectById, getLearningObjectsFromPath} from "../../src/services/learningObjects"; +import { + getLearningObjectById, + getLearningObjectsFromPath +} from "../../src/services/learningObjects"; import {fetchLearningPaths} from "../../src/services/learningPaths"; // Mock API functions @@ -35,9 +38,7 @@ describe('getLearningObjectById', () => { description: 'A test object', target_ages: [10, 12], content_type: 'markdown', - content_location: '', - skos_concepts: [], - return_value: undefined, + content_location: '' }; it('✅ Should return a filtered learning object when API provides data', async () => { @@ -62,9 +63,7 @@ describe('getLearningObjectById', () => { description: 'A test object', targetAges: [10, 12], contentType: 'markdown', - contentLocation: '', - skosConcepts: [], - returnValue: undefined, + contentLocation: '' }); }); @@ -80,19 +79,44 @@ describe('getLearningObjectsFromPath', () => { const hruid = 'test-path'; const language = 'en'; - it('⚠️ Should return an empty array if API returns an empty path response', async () => { + it('✅ Should not give error or warning', async () => { + const mockPathResponse: LearningPath[] = [{ + _id: 'path-1', + hruid, + language, + title: 'Test Path', + description: '', + num_nodes: 1, + num_nodes_left: 0, + nodes: [], + keywords: '', + target_ages: [], + min_age: 10, + max_age: 12, + __order: 1, + }]; + + vi.mocked(fetchLearningPaths).mockResolvedValueOnce({ + success: true, + source: 'Test Source', + data: mockPathResponse + }); + + const result = await getLearningObjectsFromPath(hruid, language); + expect(result).toEqual([]); + }); + + it('⚠️ Should give a warning', async () => { vi.mocked(fetchLearningPaths).mockResolvedValueOnce({success: false, source: 'Test Source', data: []}); const result = await getLearningObjectsFromPath(hruid, language); - expect(result).toEqual([]); }); - it('❌ Should return an empty array and log an error if fetchLearningPaths fails', async () => { + it('❌ Should give an error', async () => { vi.mocked(fetchLearningPaths).mockRejectedValueOnce(new Error('API Error')); const result = await getLearningObjectsFromPath(hruid, language); - expect(result).toEqual([]); }); }); From 09bf765e8c71fdfde950a43ae1ea80b1decefd5f Mon Sep 17 00:00:00 2001 From: Lint Action Date: Wed, 12 Mar 2025 19:34:18 +0000 Subject: [PATCH 5/7] style: fix linting issues met Prettier --- .../tests/service/learning-objects.test.ts | 61 +++++++++---------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/backend/tests/service/learning-objects.test.ts b/backend/tests/service/learning-objects.test.ts index 82729629..130c237e 100644 --- a/backend/tests/service/learning-objects.test.ts +++ b/backend/tests/service/learning-objects.test.ts @@ -1,13 +1,8 @@ -import {describe, it, expect, vi} from 'vitest'; -import { - LearningObjectMetadata, LearningPath, -} from "../../src/interfaces/learningPath"; -import {fetchWithLogging} from "../../src/util/apiHelper"; -import { - getLearningObjectById, - getLearningObjectsFromPath -} from "../../src/services/learningObjects"; -import {fetchLearningPaths} from "../../src/services/learningPaths"; +import { describe, it, expect, vi } from 'vitest'; +import { LearningObjectMetadata, LearningPath } from '../../src/interfaces/learningPath'; +import { fetchWithLogging } from '../../src/util/apiHelper'; +import { getLearningObjectById, getLearningObjectsFromPath } from '../../src/services/learningObjects'; +import { fetchLearningPaths } from '../../src/services/learningPaths'; // Mock API functions vi.mock('../../src/util/apiHelper', () => ({ @@ -18,7 +13,6 @@ vi.mock('../../src/services/learningPaths', () => ({ fetchLearningPaths: vi.fn(), })); - describe('getLearningObjectById', () => { const hruid = 'test-object'; const language = 'en'; @@ -33,12 +27,12 @@ describe('getLearningObjectById', () => { estimated_time: 120, available: true, teacher_exclusive: false, - educational_goals: [{source: 'source', id: 'id'}], + educational_goals: [{ source: 'source', id: 'id' }], keywords: ['robotics'], description: 'A test object', target_ages: [10, 12], content_type: 'markdown', - content_location: '' + content_location: '', }; it('✅ Should return a filtered learning object when API provides data', async () => { @@ -58,12 +52,12 @@ describe('getLearningObjectById', () => { estimatedTime: 120, available: true, teacherExclusive: false, - educationalGoals: [{source: 'source', id: 'id'}], + educationalGoals: [{ source: 'source', id: 'id' }], keywords: ['robotics'], description: 'A test object', targetAges: [10, 12], contentType: 'markdown', - contentLocation: '' + contentLocation: '', }); }); @@ -74,32 +68,33 @@ describe('getLearningObjectById', () => { }); }); - describe('getLearningObjectsFromPath', () => { const hruid = 'test-path'; const language = 'en'; it('✅ Should not give error or warning', async () => { - const mockPathResponse: LearningPath[] = [{ - _id: 'path-1', - hruid, - language, - title: 'Test Path', - description: '', - num_nodes: 1, - num_nodes_left: 0, - nodes: [], - keywords: '', - target_ages: [], - min_age: 10, - max_age: 12, - __order: 1, - }]; + const mockPathResponse: LearningPath[] = [ + { + _id: 'path-1', + hruid, + language, + title: 'Test Path', + description: '', + num_nodes: 1, + num_nodes_left: 0, + nodes: [], + keywords: '', + target_ages: [], + min_age: 10, + max_age: 12, + __order: 1, + }, + ]; vi.mocked(fetchLearningPaths).mockResolvedValueOnce({ success: true, source: 'Test Source', - data: mockPathResponse + data: mockPathResponse, }); const result = await getLearningObjectsFromPath(hruid, language); @@ -107,7 +102,7 @@ describe('getLearningObjectsFromPath', () => { }); it('⚠️ Should give a warning', async () => { - vi.mocked(fetchLearningPaths).mockResolvedValueOnce({success: false, source: 'Test Source', data: []}); + vi.mocked(fetchLearningPaths).mockResolvedValueOnce({ success: false, source: 'Test Source', data: [] }); const result = await getLearningObjectsFromPath(hruid, language); expect(result).toEqual([]); From 0e2f9e5359610956a5552d5874a61a104aa1a4e7 Mon Sep 17 00:00:00 2001 From: Joyelle Ndagijimana Date: Thu, 13 Mar 2025 09:35:35 +0100 Subject: [PATCH 6/7] =?UTF-8?q?test:=20=C3=A9=C3=A9n=20van=20de=20test=20v?= =?UTF-8?q?erbeterd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/tests/service/learning-paths.test.ts | 35 ++++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/backend/tests/service/learning-paths.test.ts b/backend/tests/service/learning-paths.test.ts index 8289a5e8..3749a986 100644 --- a/backend/tests/service/learning-paths.test.ts +++ b/backend/tests/service/learning-paths.test.ts @@ -1,7 +1,7 @@ -import { describe, it, expect, vi } from 'vitest'; -import { fetchLearningPaths, searchLearningPaths } from '../../src/services/learningPaths'; -import { fetchWithLogging } from '../../src/util/apiHelper'; -import { LearningPathResponse } from '../../src/interfaces/learningPath'; +import {describe, it, expect, vi} from 'vitest'; +import {fetchLearningPaths, searchLearningPaths} from '../../src/services/learningPaths'; +import {fetchWithLogging} from '../../src/util/apiHelper'; +import {LearningPathResponse} from '../../src/interfaces/learningPath'; // Mock the fetchWithLogging module using vi vi.mock('../../src/util/apiHelper', () => ({ @@ -13,7 +13,7 @@ describe('fetchLearningPaths', () => { const mockHruids = ['pn_werking', 'art1']; const language = 'en'; const source = 'Test Source'; - const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; + const mockResponse = [{title: 'Test Path', hruids: mockHruids}]; it('✅ Should return a successful response when HRUIDs are provided', async () => { // Mock the function to return mockResponse @@ -49,14 +49,27 @@ describe('fetchLearningPaths', () => { }); describe('searchLearningPaths', () => { - const query = 'robotics'; - const language = 'en'; + const query = 'https://dwengo.org/backend/api/learningPath/getPathsFromIdList?pathIdList=%7B%22hruids%22:%5B%22pn_werking%22,%22un_artificiele_intelligentie%22%5D%7D&language=nl'; + const language = 'nl'; it('✅ Should return search results when API responds with data', async () => { - const mockResults = [ - { title: 'Robotics Basics', hruids: ['robotics_101'] }, - { title: 'Advanced Robotics', hruids: ['robotics_advanced'] }, - ]; + + + const mockResults = [{ + _id: '67b4488c9dadb305c4104618', + language: 'nl', + hruid: 'pn_werking', + title: 'Werken met notebooks', + description: 'Een korte inleiding tot Python notebooks. Hoe ga je gemakkelijk en efficiënt met de notebooks aan de slag?', + num_nodes: 0, + num_nodes_left: 0, + nodes: [], + keywords: 'Python KIKS Wiskunde STEM AI', + target_ages: [14, 15, 16, 17, 18], + min_age: 14, + max_age: 18, + __order: 0 + }]; // Mock fetchWithLogging to return search results vi.mocked(fetchWithLogging).mockResolvedValue(mockResults); From 3d3bf6dba4957feb0a7aae5326d932bfe00b039a Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 08:36:15 +0000 Subject: [PATCH 7/7] style: fix linting issues met Prettier --- backend/tests/service/learning-paths.test.ts | 47 ++++++++++---------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/backend/tests/service/learning-paths.test.ts b/backend/tests/service/learning-paths.test.ts index 3749a986..c002dbac 100644 --- a/backend/tests/service/learning-paths.test.ts +++ b/backend/tests/service/learning-paths.test.ts @@ -1,7 +1,7 @@ -import {describe, it, expect, vi} from 'vitest'; -import {fetchLearningPaths, searchLearningPaths} from '../../src/services/learningPaths'; -import {fetchWithLogging} from '../../src/util/apiHelper'; -import {LearningPathResponse} from '../../src/interfaces/learningPath'; +import { describe, it, expect, vi } from 'vitest'; +import { fetchLearningPaths, searchLearningPaths } from '../../src/services/learningPaths'; +import { fetchWithLogging } from '../../src/util/apiHelper'; +import { LearningPathResponse } from '../../src/interfaces/learningPath'; // Mock the fetchWithLogging module using vi vi.mock('../../src/util/apiHelper', () => ({ @@ -13,7 +13,7 @@ describe('fetchLearningPaths', () => { const mockHruids = ['pn_werking', 'art1']; const language = 'en'; const source = 'Test Source'; - const mockResponse = [{title: 'Test Path', hruids: mockHruids}]; + const mockResponse = [{ title: 'Test Path', hruids: mockHruids }]; it('✅ Should return a successful response when HRUIDs are provided', async () => { // Mock the function to return mockResponse @@ -49,27 +49,28 @@ describe('fetchLearningPaths', () => { }); describe('searchLearningPaths', () => { - const query = 'https://dwengo.org/backend/api/learningPath/getPathsFromIdList?pathIdList=%7B%22hruids%22:%5B%22pn_werking%22,%22un_artificiele_intelligentie%22%5D%7D&language=nl'; + const query = + 'https://dwengo.org/backend/api/learningPath/getPathsFromIdList?pathIdList=%7B%22hruids%22:%5B%22pn_werking%22,%22un_artificiele_intelligentie%22%5D%7D&language=nl'; const language = 'nl'; it('✅ Should return search results when API responds with data', async () => { - - - const mockResults = [{ - _id: '67b4488c9dadb305c4104618', - language: 'nl', - hruid: 'pn_werking', - title: 'Werken met notebooks', - description: 'Een korte inleiding tot Python notebooks. Hoe ga je gemakkelijk en efficiënt met de notebooks aan de slag?', - num_nodes: 0, - num_nodes_left: 0, - nodes: [], - keywords: 'Python KIKS Wiskunde STEM AI', - target_ages: [14, 15, 16, 17, 18], - min_age: 14, - max_age: 18, - __order: 0 - }]; + const mockResults = [ + { + _id: '67b4488c9dadb305c4104618', + language: 'nl', + hruid: 'pn_werking', + title: 'Werken met notebooks', + description: 'Een korte inleiding tot Python notebooks. Hoe ga je gemakkelijk en efficiënt met de notebooks aan de slag?', + num_nodes: 0, + num_nodes_left: 0, + nodes: [], + keywords: 'Python KIKS Wiskunde STEM AI', + target_ages: [14, 15, 16, 17, 18], + min_age: 14, + max_age: 18, + __order: 0, + }, + ]; // Mock fetchWithLogging to return search results vi.mocked(fetchWithLogging).mockResolvedValue(mockResults);