-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from kartAI/feat/20-cadaid-results-page
Feat/20 cadaid results page
- Loading branch information
Showing
25 changed files
with
654 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
describe("CadaidPage E2E Tests", () => { | ||
const ROUTES = ["for-soknad/cadaid", "for-soknad/cadaid"]; | ||
|
||
ROUTES.forEach((route) => { | ||
describe(`Route: ${route}`, () => { | ||
beforeEach(() => { | ||
// Visit the CADAiD page before each test | ||
cy.visit(`/${route}`); | ||
}); | ||
|
||
it("should upload files successfully and display results", () => { | ||
// Intercept the upload API and mock the response | ||
cy.intercept("POST", "http://localhost:5001/detect/", { | ||
statusCode: 200, | ||
fixture: "mockResponses/detections.json", | ||
}).as("uploadFiles"); | ||
|
||
// Upload sample1.pdf and sample2.png | ||
cy.get('input[type="file"]').attachFile([ | ||
"files/sample1.pdf", | ||
"files/sample2.png", | ||
]); | ||
|
||
// Wait for the upload API call | ||
cy.wait("@uploadFiles").its("response.statusCode").should("eq", 200); | ||
|
||
// Check if files are listed in FileList using data-cy | ||
cy.get("[data-cy=file-list]").within(() => { | ||
cy.contains("sample1.pdf").should("be.visible"); | ||
cy.contains("sample2.png").should("be.visible"); | ||
}); | ||
|
||
// Check if results are displayed | ||
cy.contains("Resultater fra CADAiD").should("be.visible"); | ||
cy.contains("plantegning").should("be.visible"); | ||
cy.contains("fasade").should("be.visible"); | ||
cy.contains("situasjonskart").should("be.visible"); | ||
cy.contains("snitt").should("not.exist"); // Assuming 'snitt' is missing | ||
}); | ||
|
||
it("should handle upload errors gracefully", () => { | ||
// Handle uncaught exceptions to prevent Cypress from failing the test | ||
cy.on("uncaught:exception", (err, runnable) => { | ||
return false; // Prevents Cypress from failing the test | ||
}); | ||
|
||
// Intercept the upload API and mock an error response | ||
cy.intercept("POST", "http://localhost:5001/detect/", { | ||
statusCode: 500, | ||
fixture: "mockResponses/error.json", | ||
}).as("uploadFilesError"); | ||
|
||
// Upload invalid.txt | ||
cy.get('input[type="file"]').attachFile("files/invalid.txt"); | ||
|
||
// Instead of waiting for the network request, check for the validation error | ||
cy.contains("Invalid file type.").should("be.visible"); | ||
}); | ||
|
||
it("should remove a file and its results", () => { | ||
// Intercept the upload API and mock the response | ||
cy.intercept("POST", "http://localhost:5001/detect/", { | ||
statusCode: 200, | ||
fixture: "mockResponses/detections.json", | ||
}).as("uploadFiles"); | ||
|
||
// Upload sample1.pdf | ||
cy.get('input[type="file"]').attachFile("files/sample1.pdf"); | ||
|
||
// Wait for the upload API call | ||
cy.wait("@uploadFiles").its("response.statusCode").should("eq", 200); | ||
|
||
// Ensure the file is listed | ||
cy.contains("sample1.pdf").should("be.visible"); | ||
|
||
// Remove the file | ||
cy.contains("sample1.pdf") | ||
.parent("li") | ||
.within(() => { | ||
cy.get('button[aria-label="Remove file sample1.pdf"]').click(); | ||
}); | ||
|
||
// Ensure the file is removed from the list | ||
cy.contains("sample1.pdf").should("not.exist"); | ||
|
||
// Ensure the corresponding result is removed | ||
cy.contains("plantegning").should("not.exist"); | ||
}); | ||
|
||
it("should display file preview when a file is selected", () => { | ||
// Intercept the upload API and mock the response | ||
cy.intercept("POST", "http://localhost:5001/detect/", { | ||
statusCode: 200, | ||
fixture: "mockResponses/detections.json", | ||
}).as("uploadFiles"); | ||
|
||
// Upload sample1.pdf | ||
cy.get('input[type="file"]').attachFile("files/sample1.pdf"); | ||
|
||
// Wait for the upload API call | ||
cy.wait("@uploadFiles").its("response.statusCode").should("eq", 200); | ||
|
||
// Select the file from the dropdown | ||
cy.get('select[aria-label="Select file to preview"]').select( | ||
"sample1.pdf", | ||
); | ||
|
||
// Check if the FilePreview component displays the selected file | ||
cy.contains("Preview of: sample1.pdf").should("be.visible"); | ||
cy.contains("File content would be shown here (mock).").should( | ||
"be.visible", | ||
); | ||
}); | ||
|
||
it("should validate file types before uploading", () => { | ||
// Handle uncaught exceptions to prevent Cypress from failing the test | ||
cy.on("uncaught:exception", (err, runnable) => { | ||
return false; // Prevents Cypress from failing the test | ||
}); | ||
|
||
// Attempt to upload invalid.txt | ||
cy.get('input[type="file"]').attachFile("files/invalid.txt"); | ||
|
||
// Check that the file is not added to the FileList | ||
cy.contains("invalid.txt").should("not.exist"); | ||
|
||
// Check for a validation error message | ||
cy.contains("Invalid file type.").should("be.visible"); | ||
}); | ||
|
||
it("should be responsive on mobile devices", () => { | ||
// Set viewport to mobile size | ||
cy.viewport("iphone-6"); | ||
|
||
// Ensure that the main container has flex-direction column | ||
cy.get("[data-cy=main-container]") | ||
.should("have.class", "flex-col") | ||
.and("not.have.class", "flex-row"); | ||
|
||
// Check that left and right columns are full width | ||
cy.get("[data-cy=left-column]").should("have.css", "width", "100%"); | ||
cy.get("[data-cy=right-column]").should("have.css", "width", "100%"); | ||
|
||
// Check if elements stack vertically | ||
cy.get("h2").should("have.css", "margin-bottom", "1rem"); // mb-4 | ||
cy.get('select[aria-label="Select file to preview"]').should( | ||
"have.css", | ||
"width", | ||
"100%", | ||
); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Failed to upload files |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[ | ||
{ | ||
"file_name": "sample1.pdf", | ||
"drawing_type": ["plantegning"] | ||
}, | ||
{ | ||
"file_name": "sample2.png", | ||
"drawing_type": ["fasade", "situasjonskart"], | ||
"scale": "1:200", | ||
"room_names": "Bedroom, Bathroom", | ||
"cardinal_direction": "East" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"message": "Failed to upload files" | ||
} |
Binary file removed
BIN
-269 KB
...js/Navbar Dropdown -- should allow navigation by clicking on links (failed).png
Binary file not shown.
Binary file removed
BIN
-258 KB
....js/Navbar Dropdown -- should close dropdown when clicking outside (failed).png
Binary file not shown.
Binary file removed
BIN
-270 KB
...js/Navbar Dropdown -- should close the dropdown when clicked again (failed).png
Binary file not shown.
Binary file removed
BIN
-262 KB
...js/Navbar Dropdown -- should display correct links in the dropdown (failed).png
Binary file not shown.
Binary file removed
BIN
-172 KB
...bar.cy.js/Navbar Dropdown -- should open the dropdown when clicked (failed).png
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
"use client"; | ||
|
||
import React, { useState } from 'react'; | ||
import type { Detection } from '../../types/detection'; | ||
import FileList from './FileList'; | ||
import Results from './Results'; | ||
import FilePreview from './FilePreview'; | ||
|
||
async function fetchDetection(formData: FormData): Promise<Detection[]> { | ||
const response = await fetch('http://localhost:5001/detect/', { | ||
method: 'POST', | ||
body: formData, | ||
}) | ||
|
||
if (!response.ok) { | ||
throw new Error('Failed to upload files'); | ||
} | ||
|
||
return response.json() as Promise<Detection[]>; | ||
} | ||
|
||
const CadaidPage: React.FC = () => { | ||
const [isLoading, setIsLoading] = useState<boolean>(false); | ||
const [files, setFiles] = useState<File[]>([]); | ||
const [results, setResults] = useState<Detection[]>([]); | ||
const [errorMessage, setErrorMessage] = useState<string | null>(null); | ||
|
||
/** | ||
* Handles file upload by sending selected files to the backend. | ||
* @param event - The file input change event. | ||
*/ | ||
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => { | ||
if (event.target.files) { | ||
const uploadedFiles = Array.from(event.target.files); | ||
if (uploadedFiles.length === 0) { | ||
setErrorMessage('No files selected'); | ||
return; | ||
} | ||
|
||
const ALLOWED_FILE_TYPES = ['application/pdf', 'image/jpeg', 'image/png']; | ||
const invalidFiles = uploadedFiles.filter(file => !ALLOWED_FILE_TYPES.includes(file.type)); | ||
if (invalidFiles.length > 0) { | ||
setErrorMessage('Invalid file type.'); | ||
return; | ||
} | ||
|
||
setIsLoading(true); | ||
setFiles((prevFiles) => [...prevFiles, ...uploadedFiles]); | ||
|
||
const formData = new FormData(); | ||
uploadedFiles.forEach((file) => { | ||
formData.append('uploaded_files', file); | ||
}); | ||
|
||
try { | ||
const detections = await fetchDetection(formData); | ||
setResults((prevResults) => [...prevResults, ...detections]); | ||
} catch (error) { | ||
console.error(error); | ||
setErrorMessage('An error occurred while uploading files.'); | ||
} finally { | ||
setIsLoading(false); // Ensure loading state is reset | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Removes a file and its corresponding result from the state. | ||
* @param fileName - The name of the file to remove. | ||
*/ | ||
const handleFileRemove = (fileName: string) => { | ||
setFiles((prevFiles) => prevFiles.filter(file => file.name !== fileName)); | ||
setResults((prevResults) => prevResults.filter(result => result.file_name !== fileName)); | ||
}; | ||
|
||
return ( | ||
<div className="p-6 min-h-screen flex flex-col md:flex-row" data-cy="main-container"> | ||
{/* Left Column */} | ||
<div className="w-full md:w-1/3 md:pr-4" data-cy="left-column"> | ||
<FileList files={files} onRemove={handleFileRemove} onUpload={handleFileUpload}/> | ||
|
||
{isLoading && ( | ||
<div className="mb-4 flex justify-center items-center"> | ||
<div className="animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500"></div> | ||
</div> | ||
)} | ||
|
||
{errorMessage && ( | ||
<div | ||
className="mb-4 p-2 text-red-700 bg-red-100 rounded" | ||
role="alert" | ||
aria-live="assertive" | ||
data-cy="submission-validation" | ||
> | ||
{errorMessage} | ||
</div> | ||
)} | ||
|
||
<Results results={results} /> | ||
</div> | ||
|
||
{/* Right Column */} | ||
<div className="w-full md:w-2/3" data-cy="right-column"> | ||
<FilePreview files={files} /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default CadaidPage; |
Oops, something went wrong.