Skip to content

Commit

Permalink
👻 Add unit tests and hook for useAssessmentStatus
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Bolton <[email protected]>
  • Loading branch information
ibolton336 committed Mar 18, 2024
1 parent 161fba8 commit 95d8c24
Show file tree
Hide file tree
Showing 9 changed files with 605 additions and 561 deletions.
466 changes: 0 additions & 466 deletions client/src/app/data/mock-questionnaire.ts

This file was deleted.

77 changes: 77 additions & 0 deletions client/src/app/hooks/useAssessmentStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// hooks/useAssessmentStatus.js
import { Assessment, Archetype, Application } from "@app/api/models";
import { useFetchArchetypes } from "@app/queries/archetypes";
import { useFetchAssessments } from "@app/queries/assessments";
import { useMemo } from "react";

export const useAssessmentStatus = (application: Application) => {
const { assessments } = useFetchAssessments();
const { archetypes } = useFetchArchetypes();

return useMemo(() => {
const applicationAssessments = assessments?.filter(
(assessment: Assessment) => assessment.application?.id === application.id
);
const inheritedArchetypes = archetypes?.filter(
(archetype: Archetype) =>
archetype.applications?.map((app) => app.id).includes(application.id)
);

const assessmentsWithArchetypes = inheritedArchetypes.map(
(inheritedArchetype) => ({
inheritedArchetype,
assessments: assessments.filter(
(assessment) => assessment.archetype?.id === inheritedArchetype.id
),
})
);

const allArchetypesAssessed =
assessmentsWithArchetypes.length > 0 &&
assessmentsWithArchetypes.every(({ inheritedArchetype, assessments }) => {
const requiredAssessments = assessments.filter(
(assessment) => assessment.required
);
return (
inheritedArchetype.assessed &&
assessments.length > 0 &&
requiredAssessments.length > 0 &&
requiredAssessments.every(
(assessment) => assessment.status === "complete"
)
);
});

const assessmentsFromArchetypesCount = assessmentsWithArchetypes.filter(
({ assessments }) => assessments.some((assessment) => assessment.required)
).length;

const assessedArchetypesCount = assessmentsWithArchetypes.filter(
({ assessments, inheritedArchetype }) =>
assessments.some(
(assessment) =>
assessment.required &&
assessment.status === "complete" &&
inheritedArchetype.assessed
)
).length;

const hasApplicationAssessmentInProgress = applicationAssessments?.some(
(assessment: Assessment) =>
assessment.status === "started" ||
assessment.status === "empty" ||
assessment.status === "complete"
);
const isDirectlyAssessed =
(application.assessed && (application.assessments?.length ?? 0) > 0) ??
false;

return {
allArchetypesAssessed,
countOfFullyAssessedArchetypes: assessedArchetypesCount,
countOfArchetypesWithRequiredAssessments: assessmentsFromArchetypesCount,
hasApplicationAssessmentInProgress,
isApplicationDirectlyAssessed: isDirectlyAssessed,
};
}, [assessments, archetypes, application]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -896,8 +896,6 @@ export const ApplicationsTable: React.FC = () => {
>
<ApplicationAssessmentStatus
application={application}
assessments={assessments}
archetypes={archetypes}
isLoading={
isFetchingApplications ||
isFetchingArchetypes ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,91 +1,17 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { Application, Archetype, Assessment } from "@app/api/models";
import { Application } from "@app/api/models";
import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus";
import { Spinner } from "@patternfly/react-core";
import { useAssessmentStatus } from "@app/hooks/useAssessmentStatus";
interface ApplicationAssessmentStatusProps {
application: Application;
assessments: Assessment[];
archetypes: Archetype[];
isLoading?: boolean;
}

export const ApplicationAssessmentStatus: React.FC<
ApplicationAssessmentStatusProps
> = ({ application, assessments, archetypes, isLoading }) => {
const { t } = useTranslation();

const applicationAssessments = assessments?.filter(
(assessment: Assessment) => assessment.application?.id === application.id
);
const inheritedArchetypes = archetypes?.filter(
(archetype: Archetype) =>
archetype.applications?.map((app) => app.id).includes(application.id)
);
const assessmentStatusInfo = React.useMemo(() => {
const assessmentsWithArchetypes = inheritedArchetypes.map(
(inheritedArchetype) => ({
inheritedArchetype,
assessments: assessments.filter(
(assessment) => assessment.archetype?.id === inheritedArchetype.id
),
})
);

const someArchetypesAssessed = assessmentsWithArchetypes.some(
({ assessments }) => assessments.length > 0
);

const allArchetypesAssessed =
assessmentsWithArchetypes.length > 0 &&
assessmentsWithArchetypes.every(({ inheritedArchetype, assessments }) => {
const requiredAssessments = assessments.filter(
(assessment) => assessment.required
);
return (
inheritedArchetype.assessed &&
assessments.length > 0 &&
requiredAssessments.length > 0 &&
requiredAssessments.every(
(assessment) => assessment.status === "complete"
)
);
});

const hasInProgressOrNotStartedRequiredAssessments =
assessmentsWithArchetypes.some(({ assessments }) =>
assessments.some(
(assessment) =>
assessment.required &&
["empty", "started"].includes(assessment.status)
)
);

const assessedArchetypesWithARequiredAssessment =
assessmentsWithArchetypes.filter(({ assessments, inheritedArchetype }) =>
assessments.some(
(assessment) =>
assessment.required &&
assessment.status === "complete" &&
inheritedArchetype.assessed
)
);
const assessedArchetypeCount =
inheritedArchetypes?.filter(
(inheritedArchetype) =>
inheritedArchetype?.assessments?.length ??
(0 > 0 && inheritedArchetype.assessed)
).length || 0;

return {
assessmentsWithArchetypes,
someArchetypesAssessed,
allArchetypesAssessed,
hasInProgressOrNotStartedRequiredAssessments,
assessedArchetypesWithARequiredAssessment,
assessedArchetypeCount,
};
}, [inheritedArchetypes, assessments]);
> = ({ application, isLoading }) => {
const assessmentStatusInfo = useAssessmentStatus(application);

if (isLoading) {
return <Spinner size="sm" />;
Expand All @@ -94,28 +20,23 @@ export const ApplicationAssessmentStatus: React.FC<
let statusPreset: IconedStatusPreset = "NotStarted"; // Default status
let tooltipCount: number = 0;

const isDirectlyAssessed =
application.assessed && (application.assessments?.length ?? 0) > 0;

const {
allArchetypesAssessed,
assessedArchetypesWithARequiredAssessment,
hasInProgressOrNotStartedRequiredAssessments,
countOfFullyAssessedArchetypes,
countOfArchetypesWithRequiredAssessments,
hasApplicationAssessmentInProgress,
isApplicationDirectlyAssessed,
} = assessmentStatusInfo;

if (isDirectlyAssessed) {
if (isApplicationDirectlyAssessed) {
statusPreset = "Completed";
} else if (allArchetypesAssessed) {
statusPreset = "InheritedAssessments";
tooltipCount = assessedArchetypesWithARequiredAssessment.length;
} else if (hasInProgressOrNotStartedRequiredAssessments) {
tooltipCount = countOfFullyAssessedArchetypes;
} else if (countOfArchetypesWithRequiredAssessments > 0) {
statusPreset = "InProgressInheritedAssessments";
tooltipCount = assessedArchetypesWithARequiredAssessment.length;
} else if (
applicationAssessments?.some(
(assessment) => assessment.status === "started"
)
) {
tooltipCount = countOfArchetypesWithRequiredAssessments;
} else if (hasApplicationAssessmentInProgress) {
statusPreset = "InProgress";
}
return <IconedStatus preset={statusPreset} tooltipCount={tooltipCount} />;
Expand Down
Loading

0 comments on commit 95d8c24

Please sign in to comment.