diff --git a/bc_obps/registration/tests/models/test_user.py b/bc_obps/registration/tests/models/test_user.py index 5b987dae2d..a3b2dd188b 100644 --- a/bc_obps/registration/tests/models/test_user.py +++ b/bc_obps/registration/tests/models/test_user.py @@ -142,13 +142,13 @@ def setUpTestData(cls): ("reportnewentrantproduction_archived", "report new entrant production", None, None), ("reportnewentrant_created", "report new entrant", None, None), ("reportnewentrant_updated", "report new entrant", None, None), - ("reportnewentrant_archived", "report new entrant", None, None), + ("reportnewentrant_archived", "report new entrant", None, None), ("reportverification_created", "report verification", None, None), ("reportverification_updated", "report verification", None, None), ("reportverification_archived", "report verification", None, None), ("reportverificationvisit_created", "report verification visit", None, None), ("reportverificationvisit_updated", "report verification visit", None, None), - ("reportverificationvisit_archived", "report verification visit", None, None), + ("reportverificationvisit_archived", "report verification visit", None, None), ("reportattachment_created", "report attachment", None, None), ("reportattachment_updated", "report attachment", None, None), ("reportattachment_archived", "report attachment", None, None), diff --git a/bc_obps/reporting/api/report_verification.py b/bc_obps/reporting/api/report_verification.py index 03e8b6b081..26beb83a6d 100644 --- a/bc_obps/reporting/api/report_verification.py +++ b/bc_obps/reporting/api/report_verification.py @@ -6,7 +6,7 @@ from reporting.schema.generic import Message from service.error_service.custom_codes_4xx import custom_codes_4xx from .router import router -from reporting.schema.report_verification import ReportVerificationIn, ReportVerificationOut, ReportVerificationVisit +from reporting.schema.report_verification import ReportVerificationIn, ReportVerificationOut from reporting.service.report_verification_service import ReportVerificationService from reporting.models import ReportVerification @@ -29,6 +29,7 @@ def get_report_verification_by_version_id( print(f"Error occurred: {e}") raise + @router.get( "/report-version/{report_version_id}/report-needs-verification", response={200: bool, custom_codes_4xx: Message}, diff --git a/bc_obps/reporting/models/report_verification_visit.py b/bc_obps/reporting/models/report_verification_visit.py index e4e694df72..9876218f43 100644 --- a/bc_obps/reporting/models/report_verification_visit.py +++ b/bc_obps/reporting/models/report_verification_visit.py @@ -31,7 +31,7 @@ class VisitType(models.TextChoices): blank=True, db_comment="The type of visit conducted (Virtual or In Person)", ) - + visit_coordinates = models.CharField( max_length=100, null=True, @@ -43,7 +43,6 @@ class VisitType(models.TextChoices): db_comment="Flag to indicate the visit is an other facility visited", default=False, ) - class Meta: db_table = 'erc"."verification_visit' diff --git a/bc_obps/reporting/schema/report_verification.py b/bc_obps/reporting/schema/report_verification.py index 0cd1902886..b17307648c 100644 --- a/bc_obps/reporting/schema/report_verification.py +++ b/bc_obps/reporting/schema/report_verification.py @@ -24,7 +24,7 @@ class Meta: 'verification_conclusion', ] -class ReportVerificationVisit(ModelSchema): +class ReportVerificationVisitSchema(ModelSchema): """ Schema for ReportVerificationVisit model """ @@ -50,7 +50,7 @@ class ReportVerificationIn(BaseReportVerification): Schema for the input of report verification data """ - report_verification_visits: List[ReportVerificationVisit] = Field( + report_verification_visits: List[ReportVerificationVisitSchema] = Field( default_factory=list ) @@ -60,7 +60,7 @@ class ReportVerificationOut(BaseReportVerification): Schema for the output of report verification data """ - report_verification_visits: List[ReportVerificationVisit] = Field(default_factory=list) + report_verification_visits: List[ReportVerificationVisitSchema] = Field(default_factory=list) class Meta(BaseReportVerification.Meta): fields = BaseReportVerification.Meta.fields + ['report_version'] \ No newline at end of file diff --git a/bc_obps/reporting/service/report_verification_service.py b/bc_obps/reporting/service/report_verification_service.py index e55c88f8bc..ab800e09b1 100644 --- a/bc_obps/reporting/service/report_verification_service.py +++ b/bc_obps/reporting/service/report_verification_service.py @@ -26,7 +26,7 @@ def get_report_verification_by_version_id( ReportVerificationOut schema """ report_verification = ReportVerification.objects.get(report_version__id=report_version_id) - # report_verification.report_verification_visits = report_verification.report_verification_visits.all() + # report_verification.report_verification_visits = report_verification.report_verification_visits.all() return report_verification @staticmethod @@ -78,10 +78,10 @@ def save_report_verification(version_id: int, data: ReportVerificationIn) -> Rep visit_ids_to_keep.append(visit.id) # Delete any visits not included in the provided data - ReportVerificationVisit.objects.filter( - report_verification=report_verification - ).exclude(id__in=visit_ids_to_keep).delete() - + ReportVerificationVisit.objects.filter(report_verification=report_verification).exclude( + id__in=visit_ids_to_keep + ).delete() + # Fetch ReportVerificationVisit instances corresponding to the IDs visit_instances_to_keep = ReportVerificationVisit.objects.filter(id__in=visit_ids_to_keep) diff --git a/bc_obps/reporting/tests/api/test_report_verification_api.py b/bc_obps/reporting/tests/api/test_report_verification_api.py index 31140809fb..28e53769c0 100644 --- a/bc_obps/reporting/tests/api/test_report_verification_api.py +++ b/bc_obps/reporting/tests/api/test_report_verification_api.py @@ -2,7 +2,6 @@ from unittest.mock import patch, MagicMock, AsyncMock from registration.tests.utils.helpers import CommonTestSetup, TestUtils from registration.utils import custom_reverse_lazy -from reporting.models import ReportVerificationVisit from reporting.schema.report_verification import ReportVerificationIn from reporting.models.report_verification import ReportVerification @@ -11,7 +10,7 @@ class TestSaveReportVerificationApi(CommonTestSetup): def setup_method(self): self.report_version = baker.make_recipe('reporting.tests.utils.report_version') self.report_verification = baker.make_recipe('reporting.tests.utils.report_verification') - + # Create related ReportVerificationVisit instances and link them report_verification_visits = baker.make_recipe( "reporting.tests.utils.report_verification_visit", @@ -58,9 +57,9 @@ def test_returns_verification_data_for_report_version_id( assert response_json["accredited_by"] == self.report_verification.accredited_by assert response_json["scope_of_verification"] == self.report_verification.scope_of_verification assert response_json["threats_to_independence"] == self.report_verification.threats_to_independence - assert response_json["verification_conclusion"] == self.report_verification.verification_conclusion + assert response_json["verification_conclusion"] == self.report_verification.verification_conclusion assert len(response_json["report_verification_visits"]) == 2 - + """Tests for the get_report_needs_verification endpoint.""" @patch("reporting.service.report_verification_service.ReportVerificationService.get_report_needs_verification") @@ -128,19 +127,19 @@ def test_returns_data_as_provided_by_the_service( threats_to_independence=False, verification_conclusion="Positive", # VerificationConclusion choices: "Positive", "Modified", "Negative" report_verification_visits=[ # Including visits in the payload - { - "visit_name": "Visit 1", - "visit_type": "In person", - "visit_coordinates": "123.456, 789.101", - "is_other_visit": True, - }, - { - "visit_name": "Visit 2", - "visit_type": "Virtual", - "visit_coordinates": "", - "is_other_visit": False, - }, - ], + { + "visit_name": "Visit 1", + "visit_type": "In person", + "visit_coordinates": "123.456, 789.101", + "is_other_visit": True, + }, + { + "visit_name": "Visit 2", + "visit_type": "Virtual", + "visit_coordinates": "", + "is_other_visit": False, + }, + ], ) mock_response = ReportVerification( report_version=self.report_version, @@ -148,8 +147,8 @@ def test_returns_data_as_provided_by_the_service( accredited_by=payload.accredited_by, scope_of_verification=payload.scope_of_verification, threats_to_independence=payload.threats_to_independence, - verification_conclusion=payload.verification_conclusion, - ) + verification_conclusion=payload.verification_conclusion, + ) mock_save_report_verification.return_value = mock_response diff --git a/bc_obps/reporting/tests/utils/baker_recipes.py b/bc_obps/reporting/tests/utils/baker_recipes.py index cea57f6948..635421f293 100644 --- a/bc_obps/reporting/tests/utils/baker_recipes.py +++ b/bc_obps/reporting/tests/utils/baker_recipes.py @@ -171,7 +171,7 @@ def json_seq(json_key="generated_json", json_value="test json value", seq_value: ReportVerificationVisit, report_verification=foreign_key(report_verification), visit_name="Default Visit Name", - visit_type=ReportVerificationVisit.VisitType.IN_PERSON, + visit_type=ReportVerificationVisit.VisitType.IN_PERSON, visit_coordinates="", is_other_visit=False, ) diff --git a/bciers/apps/reporting/src/app/components/verification/VerificationPage.tsx b/bciers/apps/reporting/src/app/components/verification/VerificationPage.tsx index 43f0d12ff6..9f16c014f1 100644 --- a/bciers/apps/reporting/src/app/components/verification/VerificationPage.tsx +++ b/bciers/apps/reporting/src/app/components/verification/VerificationPage.tsx @@ -27,12 +27,12 @@ export default async function VerificationPage({ // ๐Ÿš€ Fetch initial form data const initialData = (await getReportVerification(version_id)) || {}; - // ๐Ÿ”„ Add the visit_names property conditionally based on operationType + // ๐Ÿ”„ Add properties conditionally based on operationType if (operationType === "LFO") { + // Add the visit_names property initialData.visit_names = (initialData.report_verification_visits || []) .filter((visit: { is_other_visit: boolean }) => !visit.is_other_visit) .map((visit: { visit_name: string }) => visit.visit_name); - if ( (initialData.report_verification_visits || []).some( (visit: { is_other_visit: boolean }) => visit.is_other_visit, @@ -40,21 +40,18 @@ export default async function VerificationPage({ ) { initialData.visit_names.push("Other"); } - } - { - //TODO - } - - // ๐Ÿ”„ Add the visit_types property conditionally based on operationType - if (operationType === "LFO") { + // Add the visit_types property initialData.visit_types = (initialData.report_verification_visits || []) - .filter((visit: { is_other_visit: boolean }) => !visit.is_other_visit) + .filter( + (visit: { is_other_visit: boolean; visit_name: string }) => + !visit.is_other_visit && visit.visit_name !== "None", + ) .map((visit: { visit_name: string; visit_type: string }) => ({ visit_name: visit.visit_name, visit_type: visit.visit_type, })); - // ๐Ÿ”„ Add the visit_others property + // Add the visit_others property initialData.visit_others = ( initialData.report_verification_visits || [] ).some((visit: { is_other_visit: boolean }) => visit.is_other_visit) @@ -73,7 +70,37 @@ export default async function VerificationPage({ ) : [{}]; } else { - //TODO + const visit = initialData.report_verification_visits?.[0]; + // Add the visit_names property + if (visit) { + if (visit.is_other_visit) { + initialData.visit_names = "Other"; + } else { + initialData.visit_names = visit.visit_name; + } + // Add the visit_others property + if (visit && !visit.is_other_visit && visit.visit_name !== "None") { + initialData.visit_types = visit.visit_type; + } else { + initialData.visit_types = undefined; + } + // Add the visit_others property + if (visit && visit.is_other_visit) { + initialData.visit_others = [ + { + visit_name: visit.visit_name, + visit_coordinates: visit.visit_coordinates, + visit_type: visit.visit_type, + }, + ]; + } else { + initialData.visit_others = [{}]; + } + } else { + initialData.visit_names = undefined; + initialData.visit_types = undefined; + initialData.visit_others = [{}]; + } } // ๐Ÿš€ Fetch the list of facilities associated with the specified version ID diff --git a/bciers/apps/reporting/src/tests/components/verification/VerificationForm.test.tsx b/bciers/apps/reporting/src/tests/components/verification/VerificationForm.test.tsx deleted file mode 100644 index 3816fff266..0000000000 --- a/bciers/apps/reporting/src/tests/components/verification/VerificationForm.test.tsx +++ /dev/null @@ -1,265 +0,0 @@ -import { render, screen, waitFor, fireEvent } from "@testing-library/react"; -import { actionHandler, useRouter } from "@bciers/testConfig/mocks"; -import { - verificationSchema, - verificationUiSchema, -} from "@reporting/src/data/jsonSchema/verification/verification"; -import VerificationForm from "@reporting/src/app/components/verification/VerificationForm"; -import expectButton from "@bciers/testConfig/helpers/expectButton"; -import expectField from "@bciers/testConfig/helpers/expectField"; -import { fillMandatoryFields } from "@bciers/testConfig/helpers/fillMandatoryFields"; - -// โœจ Mocks -const mockRouterPush = vi.fn(); -useRouter.mockReturnValue({ - push: mockRouterPush, -}); - -// ๐Ÿท Constants -const config = { - buttons: { - cancel: "Back", - saveAndContinue: "Save & Continue", - }, - actionPost: { - endPoint: "reporting/report-version/3/report-verification", - method: "POST", - revalidatePath: "reporting/reports", - }, - mockVersionId: 3, - mockRouteSubmit: `/reports/3/attachments?`, -}; - -// ๐Ÿท Common Fields -const commonMandatoryFormFields = [ - { - label: "Verification body name", - type: "text", - key: "verification_body_name", - }, - { label: "Accredited by", type: "combobox", key: "accredited_by" }, - { - label: "Scope of verification", - type: "combobox", - key: "scope_of_verification", - }, - { label: "Sites visited", type: "combobox", key: "visit_name" }, - { - label: "Were there any threats to independence noted", - type: "radio", - key: "threats_to_independence", - }, - { - label: "Verification conclusion", - type: "combobox", - key: "verification_conclusion", - }, -]; - -const specificMandatoryFields = { - facility: [{ label: "Type of site visit", type: "radio", key: "visit_type" }], - other: [ - { label: "Type of site visit", type: "radio", key: "visit_type" }, - { - label: "Please indicate the site visited", - type: "text", - key: "other_facility_name", - }, - { - label: "Geographic coordinates of site", - type: "text", - key: "other_facility_coordinates", - }, - ], -}; - -const formDataSets = { - default: { - verification_body_name: "Test", - accredited_by: "SCC", - scope_of_verification: "Supplementary Report", - visit_name: "None", - threats_to_independence: "No", - verification_conclusion: "Positive", - }, - facility: { - verification_body_name: "Test", - accredited_by: "SCC", - scope_of_verification: "Supplementary Report", - visit_name: "Facility X", - visit_type: "Virtual", - threats_to_independence: "No", - verification_conclusion: "Positive", - }, - other: { - verification_body_name: "Test", - accredited_by: "SCC", - scope_of_verification: "Supplementary Report", - visit_name: "Other", - visit_type: "Virtual", - other_facility_name: "Other Facility", - other_facility_coordinates: "Lat 41; Long 35", - threats_to_independence: "No", - verification_conclusion: "Modified", - }, -}; - -// โ›๏ธ Helper function to render the form -const renderVerificationForm = () => { - render( - , - ); -}; - -// โ›๏ธ Helper function to simulate form POST submission and assert the result -const submitFormAndAssert = async ( - fields: { label: string; type: string; key: string }[], - data: Record, -) => { - actionHandler.mockReturnValueOnce({ - success: true, - }); - await fillMandatoryFields(fields, data); - const button = screen.getByRole("button", { - name: config.buttons.saveAndContinue, - }); - await waitFor(() => { - expect(button).toBeEnabled(); - }); - fireEvent.click(button); - - await waitFor(() => { - expect(screen.queryByText(/Required field/i)).not.toBeInTheDocument(); - // Assert expected behavior after submission - expect(actionHandler).toHaveBeenCalledTimes(1); - expect(mockRouterPush).toHaveBeenCalledTimes(1); - expect(mockRouterPush).toHaveBeenCalledWith(config.mockRouteSubmit); - }); -}; - -// ๐Ÿงช Test suite -describe("VerificationForm component", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("renders the form with correct fields", () => { - renderVerificationForm(); - // expectField(commonMandatoryFormFields.map((field) => field.label)); - expectButton(config.buttons.cancel); - expectButton(config.buttons.saveAndContinue); - }); - - // it("does not allow form submission if there are validation errors", async () => { - // renderVerificationForm(); - // fireEvent.click( - // screen.getByRole("button", { name: config.buttons.saveAndContinue }), - // ); - - // await waitFor(() => { - // expect(screen.queryAllByText(/Required field/i)).toHaveLength(6); - // }); - // }); - - // it( - // "fills mandatory fields for 'None' option and submits successfully", - // { - // timeout: 10000, - // }, - // async () => { - // renderVerificationForm(); - // // POST submit and assert the result - // await submitFormAndAssert( - // commonMandatoryFormFields, - // formDataSets.default, - // ); - // // Assert if actionHandler was called correctly - // expect(actionHandler).toHaveBeenCalledWith( - // config.actionPost.endPoint, - // "POST", - // config.actionPost.revalidatePath, - // { - // body: JSON.stringify({ - // verification_body_name: "Test", - // accredited_by: "SCC", - // scope_of_verification: "Supplementary Report", - // visit_name: "None", - // threats_to_independence: false, - // verification_conclusion: "Positive", - // }), - // }, - // ); - // }, - // ); - - // it( - // "fills mandatory fields for 'Facility X' option and submits successfully", - // { - // timeout: 10000, - // }, - // async () => { - // renderVerificationForm(); - // const fields = [ - // ...commonMandatoryFormFields, - // ...specificMandatoryFields.facility, - // ]; - // await submitFormAndAssert(fields, formDataSets.facility); - // }, - // ); - // it( - // "fills mandatory fields for 'Other' option and submits successfully", - // { - // timeout: 10000, - // }, - // async () => { - // renderVerificationForm(); - // const fields = [ - // ...commonMandatoryFormFields, - // ...specificMandatoryFields.other, - // ]; - // // POST submit and assert the result - // await submitFormAndAssert(fields, formDataSets.other); - // // Assertion if actionHandler was called correctly - // expect(actionHandler).toHaveBeenCalledWith( - // config.actionPost.endPoint, - // "POST", - // config.actionPost.revalidatePath, - // { - // body: JSON.stringify({ - // verification_body_name: "Test", - // accredited_by: "SCC", - // scope_of_verification: "Supplementary Report", - // visit_name: "Other", - // threats_to_independence: false, - // verification_conclusion: "Modified", - // visit_type: "Virtual", - // other_facility_name: "Other Facility", - // other_facility_coordinates: "Lat 41; Long 35", - // }), - // }, - // ); - // }, - // ); - // it("routes to the compliance summary page when the Back button is clicked", () => { - // const queryString = "?"; // Update this based on your query string logic if necessary. - // const expectedRoute = `/reports/${config.mockVersionId}/compliance-summary${queryString}`; - - // renderVerificationForm(); - - // // Click the "Back" button - // const backButton = screen.getByRole("button", { - // name: config.buttons.cancel, - // }); - // fireEvent.click(backButton); - - // // Assert that the router's push method was called with the expected route - // expect(mockRouterPush).toHaveBeenCalledTimes(1); - // expect(mockRouterPush).toHaveBeenCalledWith(expectedRoute); - // }); -}); diff --git a/bciers/apps/reporting/src/tests/components/verification/VerificationPage.test.tsx b/bciers/apps/reporting/src/tests/components/verification/VerificationPage.test.tsx deleted file mode 100644 index acc28750e9..0000000000 --- a/bciers/apps/reporting/src/tests/components/verification/VerificationPage.test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { render } from "@testing-library/react"; -import VerificationPage from "@reporting/src/app/components/verification/VerificationPage"; -import VerificationForm from "@reporting/src/app/components/verification/VerificationForm"; -import { getReportVerification } from "@reporting/src/app/utils/getReportVerification"; -import { getReportFacilityList } from "@reporting/src/app/utils/getReportFacilityList"; -import { createVerificationSchema } from "@reporting/src/app/components/verification/createVerificationSchema"; -import { getSignOffAndSubmitSteps } from "@reporting/src/app/components/taskList/5_signOffSubmit"; - -vi.mock("@reporting/src/app/components/verification/VerificationForm", () => ({ - default: vi.fn(), -})); - -vi.mock("@reporting/src/app/utils/getReportVerification", () => ({ - getReportVerification: vi.fn(), -})); - -vi.mock("@reporting/src/app/utils/getReportFacilityList", () => ({ - getReportFacilityList: vi.fn(), -})); - -vi.mock( - "@reporting/src/app/components/verification/createVerificationSchema", - () => ({ - createVerificationSchema: vi.fn(), - }), -); - -vi.mock("@reporting/src/app/utils/getReportNeedsVerification", () => ({ - getReportNeedsVerification: vi.fn(() => Promise.resolve(true)), // Mocking to return true -})); - -vi.mock("@reporting/src/app/components/taskList/5_signOffSubmit", () => ({ - getSignOffAndSubmitSteps: vi.fn(), - ActivePage: { - Verification: "Verification", - }, -})); - -const mockVerificationForm = VerificationForm as ReturnType; -const mockGetReportVerification = getReportVerification as ReturnType< - typeof vi.fn ->; -const mockGetReportFacilityList = getReportFacilityList as ReturnType< - typeof vi.fn ->; -const mockCreateVerificationSchema = createVerificationSchema as ReturnType< - typeof vi.fn ->; -const mockGetSignOffAndSubmitSteps = getSignOffAndSubmitSteps as ReturnType< - typeof vi.fn ->; - -describe("VerificationPage component", () => { - it("renders the VerificationForm component with the correct data", async () => { - const mockVersionId = 12345; - const mockInitialData = { field1: "value1", field2: "value2" }; - const mockFacilityList = { - facilities: [ - { id: 1, name: "Facility 1" }, - { id: 2, name: "Facility 2" }, - ], - }; - const mockVerificationSchema = { type: "object", properties: {} }; - const mockTaskListElements = [ - { type: "Page", title: "Verification", isActive: true }, - ]; - - mockGetReportVerification.mockResolvedValue(mockInitialData); - mockGetReportFacilityList.mockResolvedValue(mockFacilityList); - mockCreateVerificationSchema.mockReturnValue(mockVerificationSchema); - mockGetSignOffAndSubmitSteps.mockResolvedValue(mockTaskListElements); - - render(await VerificationPage({ version_id: mockVersionId })); - - expect(mockGetReportVerification).toHaveBeenCalledWith(mockVersionId); - expect(mockGetReportFacilityList).toHaveBeenCalledWith(mockVersionId); - // expect(mockCreateVerificationSchema).toHaveBeenCalledWith( - // mockFacilityList.facilities, - // ); - expect(mockGetSignOffAndSubmitSteps).toHaveBeenCalledWith( - mockVersionId, - "Verification", - true, - ); - - // expect(mockVerificationForm).toHaveBeenCalledWith( - // { - // version_id: mockVersionId, - // verificationSchema: mockVerificationSchema, - // verificationUiSchema: expect.any(Object), - // initialData: mockInitialData, - // taskListElements: mockTaskListElements, - // }, - // {}, - // ); - }); -});