Skip to content

Commit

Permalink
tests: add verification utils tests
Browse files Browse the repository at this point in the history
chore: cleanup

chore: cleanup

chore: cleanup

chore: cleanup

chore: cleanup

chore: cleanup
  • Loading branch information
shon-button committed Jan 31, 2025
1 parent 6bc31ee commit 487640d
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 180 deletions.
5 changes: 3 additions & 2 deletions bc_obps/reporting/api/report_verification.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Literal
from reporting.models.report_verification import ReportVerification
from common.permissions import authorize
from django.http import HttpRequest
from registration.decorators import handle_http_errors
Expand All @@ -8,7 +9,6 @@
from .router import router
from reporting.schema.report_verification import ReportVerificationIn, ReportVerificationOut
from reporting.service.report_verification_service import ReportVerificationService
from reporting.models import ReportVerification


@router.get(
Expand All @@ -21,9 +21,10 @@
@handle_http_errors()
def get_report_verification_by_version_id(
request: HttpRequest, report_version_id: int
) -> tuple[Literal[200], ReportVerificationOut]:
) -> tuple[Literal[200], ReportVerification]:
return 200, ReportVerificationService.get_report_verification_by_version_id(report_version_id)


@router.get(
"/report-version/{report_version_id}/report-needs-verification",
response={200: bool, custom_codes_4xx: Message},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.10 on 2025-01-27 15:40
# Generated by Django 5.0.10 on 2025-01-31 17:48

import django.db.models.deletion
from django.db import migrations, models
Expand All @@ -7,8 +7,8 @@
class Migration(migrations.Migration):

dependencies = [
('registration', '0069_V1_19_0'),
('reporting', '0045_fix_incorrect_fkey_on_deletes'),
('registration', '0070_V1_20_0'),
('reporting', '0048_remove_activitysourcetypejsonschema_invalid_if_has_unit_and_no_fuel'),
]

operations = [
Expand Down
30 changes: 23 additions & 7 deletions bc_obps/reporting/schema/report_verification.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
from ninja import ModelSchema, Field
from typing import Optional, List
from ninja import ModelSchema
from pydantic import Field

from reporting.models import ReportVerification, ReportVerificationVisit
from typing import List


class BaseReportVerification(ModelSchema):
class ReportVerificationBase(ModelSchema):
"""
Base schema for shared fields in ReportVerification schemas
"""

verification_body_name: str
accredited_by: str
scope_of_verification: str
threats_to_independence: bool
verification_conclusion: str

class Meta:
model = ReportVerification
fields = [
Expand All @@ -24,6 +32,11 @@ class ReportVerificationVisitSchema(ModelSchema):
Schema for ReportVerificationVisit model
"""

visit_name: str
visit_type: Optional[str] = Field(None)
is_other_visit: bool
visit_coordinates: str

class Meta:
model = ReportVerificationVisit
fields = [
Expand All @@ -34,20 +47,23 @@ class Meta:
]


class ReportVerificationIn(BaseReportVerification):
class ReportVerificationIn(ReportVerificationBase):
"""
Schema for the input of report verification data
"""

report_verification_visits: List[ReportVerificationVisitSchema] = Field(default_factory=list)

class Meta(ReportVerificationBase.Meta):
fields = ReportVerificationBase.Meta.fields


class ReportVerificationOut(BaseReportVerification):
class ReportVerificationOut(ReportVerificationBase):
"""
Schema for the output of report verification data
"""

report_verification_visits: List[ReportVerificationVisitSchema] = Field(default_factory=list)

class Meta(BaseReportVerification.Meta):
fields = BaseReportVerification.Meta.fields + ['report_version']
class Meta(ReportVerificationBase.Meta):
fields = ReportVerificationBase.Meta.fields + ['report_version']
2 changes: 1 addition & 1 deletion bc_obps/reporting/service/report_verification_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from reporting.models.report_verification import ReportVerification
from reporting.models.report_verification_visit import ReportVerificationVisit
from reporting.models import ReportVersion
from reporting.schema.report_verification import ReportVerificationIn

from registration.models import Operation
from reporting.service.report_additional_data import ReportAdditionalDataService
from reporting.service.compliance_service import ComplianceService
from reporting.schema.report_verification import ReportVerificationIn


class ReportVerificationService:
Expand Down
1 change: 1 addition & 0 deletions bc_obps/service/tests/test_report_version_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@ def test_report_version_cascading_models(self):
"ReportOperationRepresentative",
"ReportAdditionalData",
"ReportVerification",
"ReportVerificationVisit",
"ReportProductEmissionAllocation",
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function VerificationForm({
const handleSubmit = async () => {
// 📷 Clone formData as payload
const payload = { ...formData };
debugger;

// ➕ Update report_verification_visits property based on visit_types and visit_others
mergeVerificationData(payload);

Expand All @@ -70,8 +70,7 @@ export default function VerificationForm({
const response = await actionHandler(endpoint, method, pathToRevalidate, {
body: JSON.stringify(payload),
});
console.log(JSON.stringify(payload));
console.log(response);

// 🐜 Check for errors
if (response?.error) {
setErrors([response.error]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { sfoUiSchema } from "@reporting/src/data/jsonSchema/verification/verific
export const createVerificationUiSchema = (
schemaType: "SFO" | "LFO",
): RJSFSchema => {
// Retrieve a local copy of the base verification ui schema based
switch (schemaType) {
case "SFO":
return { ...sfoUiSchema };
case "LFO":
return { ...lfoUiSchema };
}
// Determine the schema based on the schemaType
const localUiSchema: RJSFSchema =
schemaType === "SFO" ? { ...sfoUiSchema } : { ...lfoUiSchema };

// Return the customized schema.
return localUiSchema;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,90 @@ import { describe, it, expect } from "vitest";
import { handleVerificationData } from "@reporting/src/app/utils/verification/handleVerificationData";

describe("handleVerificationData", () => {
it("should lock selection to 'None' and clear other fields if only 'None' is selected", () => {
const input = {
it("should remove 'None' if other selections are made", () => {
const data = {
visit_names: ["None", "Facility 1"],
visit_types: [],
visit_others: [],
};
const result = handleVerificationData(data, "default");
expect(result.visit_names).toEqual(["Facility 1"]);
});

it("should lock to 'None' and clear other fields if only 'None' is selected", () => {
const data = {
visit_names: ["None"],
visit_types: [{ visit_name: "Test", visit_type: "A" }],
visit_others: [{ visit_name: "Other" }],
visit_types: [{ visit_name: "Old" }],
visit_others: [{ key: "value" }],
};
const result = handleVerificationData(input, "LFO");
const result = handleVerificationData(data, "default");
expect(result.visit_names).toEqual(["None"]);
expect(result.visit_types).toEqual([]);
expect(result.visit_others).toEqual([{}]);
});

it("should remove 'None' if other selections are made", () => {
const input = {
visit_names: ["None", "Facility A"],
it("should enforce maxItem=1 for 'SFO' operation type", () => {
const data = {
visit_names: ["Facility 1", "Facility 2"],
visit_types: [],
visit_others: [],
};
const result = handleVerificationData(input, "LFO");
expect(result.visit_names).toEqual(["Facility A"]);
const result = handleVerificationData(data, "SFO");
expect(result.visit_names).toEqual(["Facility 2"]); // Last selected should be retained
});

it("should enforce only one selection for 'SFO', keeping the last selected value", () => {
const input = {
visit_names: ["Facility A", "Facility B"],
it("should update visit_types based on visit_names", () => {
const data = {
visit_names: ["Facility 1", "Facility 2"],
visit_types: [],
visit_others: [],
};
const result = handleVerificationData(input, "SFO");
expect(result.visit_names).toEqual(["Facility B"]);
const result = handleVerificationData(data, "default");
expect(result.visit_types).toEqual([
{ visit_name: "Facility 1", visit_type: "" },
{ visit_name: "Facility 2", visit_type: "" },
]);
});

it("should clear visit types and visit others when 'None' is the last selected for 'SFO'", () => {
const input = {
visit_names: ["Facility A", "None"],
visit_types: [{ visit_name: "Facility A", visit_type: "A" }],
visit_others: [{ visit_name: "Other" }],
it("should preserve existing visit_types if present", () => {
const data = {
visit_names: ["Facility 1"],
visit_types: [{ visit_name: "Facility 1", visit_type: "In-Person" }],
visit_others: [],
};
const result = handleVerificationData(input, "SFO");
expect(result.visit_names).toEqual(["None"]);
const result = handleVerificationData(data, "default");
expect(result.visit_types).toEqual([
{ visit_name: "Facility 1", visit_type: "In-Person" },
]);
});

it("should set visit_types to empty if only 'None' is selected", () => {
const data = {
visit_names: ["None"],
visit_types: [{ visit_name: "Facility 1" }],
visit_others: [],
};
const result = handleVerificationData(data, "default");
expect(result.visit_types).toEqual([]);
});

it("should clear visit_others if 'Other' is not selected", () => {
const data = {
visit_names: ["Facility 1"],
visit_types: [],
visit_others: [{ visit_name: "Other Visit" }],
};
const result = handleVerificationData(data, "default");
expect(result.visit_others).toEqual([{}]);
});

it("should correctly update visit_types excluding 'Other' and 'None'", () => {
const input = {
visit_names: ["Facility A", "Other", "None"],
it("should retain visit_others if 'Other' is selected", () => {
const data = {
visit_names: ["Other"],
visit_types: [],
visit_others: [],
visit_others: [{ visit_name: "Other Visit" }],
};
const result = handleVerificationData(input, "LFO");
expect(result.visit_types).toEqual([
{ visit_name: "Facility A", visit_type: "" },
]);
const result = handleVerificationData(data, "default");
expect(result.visit_others).toEqual([{ visit_name: "Other Visit" }]);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// 🛠️ Function to manages interaction with the data and form
// Required(?) when JSON Schema validators struggle with conditional logic based on dynamic enums
// Required(?) when using an array, visit_names, requiring a MultiSelectWidget but with a maxItem rules
export function handleVerificationData(
updatedData: any,
operationType: string,
Expand All @@ -9,12 +6,20 @@ export function handleVerificationData(

if (selectedValues.includes("None")) {
if (selectedValues.length > 1) {
// Remove "None" if other selections are made
updatedData.visit_names = selectedValues.filter(
(value: string) => value !== "None",
);
// If "None" is the last selected item, clear everything
if (selectedValues[selectedValues.length - 1] === "None") {
updatedData.visit_names = ["None"];
updatedData.visit_types = [];
updatedData.visit_others = [{}];
return updatedData;
} else {
// Otherwise, remove "None"
updatedData.visit_names = selectedValues.filter(
(value: string) => value !== "None",
);
}
} else {
// Lock to "None" and clear other fields
// If only "None" is selected, lock it and clear other fields
updatedData.visit_names = ["None"];
updatedData.visit_types = [];
updatedData.visit_others = [{}];
Expand All @@ -23,15 +28,11 @@ export function handleVerificationData(
}

if (operationType === "SFO" && selectedValues.length > 1) {
// Ensure "SFO" can only have one item, taking the last selected
// Ensure "SFO" visit_names maxItem=1
const lastSelected = selectedValues[selectedValues.length - 1];
updatedData.visit_names = [lastSelected];

if (lastSelected === "None") {
// Clear visit types and visit others only if the value is "None"
updatedData.visit_types = [];
updatedData.visit_others = [{}];
}
// Set the last selected item as the only value for visit_names
updatedData.visit_names = [lastSelected];
}

// Update `visit_types` for each facility except "Other" and "None"
Expand All @@ -46,5 +47,10 @@ export function handleVerificationData(
return existingVisitType || { visit_name, visit_type: "" };
});

// Clear visit_others if "Other" is not selected
if (!updatedData.visit_names.includes("Other")) {
updatedData.visit_others = [{}];
}

return updatedData;
}
Loading

0 comments on commit 487640d

Please sign in to comment.