diff --git a/web-frontend/src/app/optimize-and-export/page.test.tsx b/web-frontend/src/app/optimize-and-export/page.test.tsx index 364805d9..c310c911 100644 --- a/web-frontend/src/app/optimize-and-export/page.test.tsx +++ b/web-frontend/src/app/optimize-and-export/page.test.tsx @@ -624,6 +624,14 @@ describe('OptimizeAndExportPage error handling', () => { }); render(); + const solverSelect = screen.getByRole('combobox', { name: /solver/i }); + const solverOptions = Array.from((solverSelect as HTMLSelectElement).options); + expect(solverSelect).toHaveValue('ortools/cp-sat'); + expect(solverOptions.map(option => option.text)).toContain('OR-Tools / CP-SAT (CPU)'); + expect(solverOptions.map(option => option.text)).toContain('PuLP / cuOpt (GPU)'); + expect(solverOptions.map(option => option.value)).not.toContain('pulp/cbc'); + + await user.selectOptions(solverSelect, 'pulp/cuopt'); await user.click(screen.getByRole('button', { name: /optimize and download/i })); await expect(screen.findByText('Schedule optimized and downloaded successfully!')).resolves.toBeInTheDocument(); @@ -632,6 +640,11 @@ describe('OptimizeAndExportPage error handling', () => { expect(screen.getByText('OPTIMAL')).toBeInTheDocument(); expect(fetch).toHaveBeenCalledWith('http://localhost:8000/optimize', expect.objectContaining({ method: 'POST' })); + const optimizePostCall = (fetch as unknown as ReturnType).mock.calls.find( + ([url, options]) => url === 'http://localhost:8000/optimize' && options?.method === 'POST' + ); + expect(optimizePostCall?.[1].body).toBeInstanceOf(FormData); + expect((optimizePostCall?.[1].body as FormData).get('solver')).toBe('pulp/cuopt'); expect(fetch).toHaveBeenCalledWith( 'http://localhost:8000/optimize/opt_test', expect.objectContaining({ method: 'GET' }) diff --git a/web-frontend/src/app/optimize-and-export/page.tsx b/web-frontend/src/app/optimize-and-export/page.tsx index 2b0fae0a..6761757a 100644 --- a/web-frontend/src/app/optimize-and-export/page.tsx +++ b/web-frontend/src/app/optimize-and-export/page.tsx @@ -272,6 +272,7 @@ export default function OptimizeAndExportPage() { const [apiEndpoint, setApiEndpoint] = useState(INITIAL_BACKEND_API_URL); const [prettifyArg, setPrettifyArg] = useState(true); const [anonymizeScheduleData, setAnonymizeScheduleData] = useState(true); + const [solverArg, setSolverArg] = useState('ortools/cp-sat'); const [timeoutArg, setTimeoutArg] = useState(300); const [timeoutError, setTimeoutError] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -655,6 +656,7 @@ export default function OptimizeAndExportPage() { } formData.append('timeout', String(timeoutArg)); + formData.append('solver', solverArg); const createResponse = await fetch(`${normalizeEndpoint(apiEndpoint)}/optimize`, { method: 'POST', @@ -881,6 +883,21 @@ export default function OptimizeAndExportPage() { +
+ + +
+