Repository: bcgov/PSP
Pull request #4745: PSP-10279 : FT:LTSA Service degradation notification is popping up on the screen even after service is looking fine
Author: login: eddherrera
Labels: name: bug
description: Something isn't working
Created: 2025-04-09T17:53:29Z | Merged: 2025-04-09T18:24:15Z



Diff:
diff --git a/source/backend/api/Helpers/Healthchecks/PimsLtsaHealthcheck.cs b/source/backend/api/Helpers/Healthchecks/PimsLtsaHealthcheck.cs
index 19717dc961..f506eafe6a 100644
--- a/source/backend/api/Helpers/Healthchecks/PimsLtsaHealthcheck.cs
+++ b/source/backend/api/Helpers/Healthchecks/PimsLtsaHealthcheck.cs
@@ -26,7 +26,7 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context
                 if (!_pid.HasValue || _pid.Value == 0)
                 {
                     var token = await _ltsaService.GetTokenAsync();
-                    if (token.AccessToken != null)
+                    if (token.AccessToken is null)
                     {
                         return new HealthCheckResult(HealthStatus.Degraded, $"received invalid token response from LTSA");
                     }
diff --git a/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx b/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx
index b24ab445e3..69b7cd9ea5 100644
--- a/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx
+++ b/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx
@@ -1,4 +1,4 @@
-import { act, render, RenderOptions } from '@/utils/test-utils';
+import { act, render, RenderOptions, waitForEffects } from '@/utils/test-utils';
 
 import { HealthcheckContainer, IHealthcheckContainerProps } from './HealthcheckContainer';
 import { useApiHealth } from '@/hooks/pims-api/useApiHealth';
@@ -120,4 +120,11 @@ describe('Healthcheck container', () => {
 
     expect(updateHealthcheckResult).toHaveBeenCalledWith(true);
   });
+
+  it(`sets the right amount of healtcheck issues`, async () => {
+    await setup();
+    await waitForEffects();
+
+    expect(viewProps.systemChecks.length).toBe(2);
+  });
 });
diff --git a/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx b/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx
index e9687e446d..3785cd96d9 100644
--- a/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx
+++ b/source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx
@@ -1,12 +1,12 @@
 import axios, { AxiosError } from 'axios';
 import { useCallback, useEffect, useState } from 'react';
 
-import IHealthcheckResponse from '@/hooks/pims-api/interfaces/IHealthcheckResponse';
+import IHealthCheckResponse from '@/hooks/pims-api/interfaces/IHealthcheckResponse';
 import ISystemCheck from '@/hooks/pims-api/interfaces/ISystemCheck';
 import { useApiHealth } from '@/hooks/pims-api/useApiHealth';
 import useKeycloakWrapper from '@/hooks/useKeycloakWrapper';
 import { IApiError } from '@/interfaces/IApiError';
-import { HealthcheckMessagesTypesEnum } from '@/layouts/models/HealthcheckMessagesTypes';
+import { HealthCheckMessagesTypesEnum } from '@/layouts/models/HealthcheckMessagesTypes';
 import { useTenant } from '@/tenants/useTenant';
 
 import { IHealthCheckIssue, IHealthCheckViewProps } from './HealthcheckView';
@@ -30,39 +30,63 @@ export const HealthcheckContainer: React.FunctionComponent<IHealthcheckContainer
   const keycloak = useKeycloakWrapper();
 
   const checkExternalSystemStatus = useCallback(
-    (response: IHealthcheckResponse, service: HealthcheckMessagesTypesEnum) => {
+    (
+      response: IHealthCheckResponse,
+      service: HealthCheckMessagesTypesEnum,
+      issues: IHealthCheckIssue[],
+    ) => {
       if (response && response.status !== 'Healthy') {
-        setHealthCheckIssues([
-          ...healthCheckIssues,
-          {
-            key: service,
-            msg: pimsHealthcheckMessages[HealthcheckMessagesTypesEnum[service]],
-          },
-        ]);
+        const newIssue: IHealthCheckIssue = {
+          key: service,
+          msg: pimsHealthcheckMessages[HealthCheckMessagesTypesEnum[service]],
+        };
+
+        issues.push(newIssue);
       }
     },
-    [healthCheckIssues, pimsHealthcheckMessages],
+    [pimsHealthcheckMessages],
   );
 
   const checkAllSystemsHealth = useCallback(
     (response: ISystemCheck) => {
+      const issuesSummary: IHealthCheckIssue[] = [];
       checkExternalSystemStatus(
         response.entries?.Geoserver,
-        HealthcheckMessagesTypesEnum.GEOSERVER,
+        HealthCheckMessagesTypesEnum.GEOSERVER,
+        issuesSummary,
       );
 
       checkExternalSystemStatus(
         response.entries?.PmbcExternalApi,
-        HealthcheckMessagesTypesEnum.PMBC,
+        HealthCheckMessagesTypesEnum.PMBC,
+        issuesSummary,
       );
 
-      checkExternalSystemStatus(response.entries?.Mayan, HealthcheckMessagesTypesEnum.MAYAN);
+      checkExternalSystemStatus(
+        response.entries?.Mayan,
+        HealthCheckMessagesTypesEnum.MAYAN,
+        issuesSummary,
+      );
+
+      checkExternalSystemStatus(
+        response.entries?.Ltsa,
+        HealthCheckMessagesTypesEnum.LTSA,
+        issuesSummary,
+      );
 
-      checkExternalSystemStatus(response.entries?.Ltsa, HealthcheckMessagesTypesEnum.LTSA);
+      checkExternalSystemStatus(
+        response.entries?.Geocoder,
+        HealthCheckMessagesTypesEnum.GEOCODER,
+        issuesSummary,
+      );
 
-      checkExternalSystemStatus(response.entries?.Geocoder, HealthcheckMessagesTypesEnum.GEOCODER);
+      checkExternalSystemStatus(
+        response.entries?.Cdogs,
+        HealthCheckMessagesTypesEnum.CDOGS,
+        issuesSummary,
+      );
 
-      checkExternalSystemStatus(response.entries?.Cdogs, HealthcheckMessagesTypesEnum.CDOGS);
+      setHealthCheckIssues(issuesSummary);
     },
     [checkExternalSystemStatus],
   );
@@ -75,9 +99,9 @@ export const HealthcheckContainer: React.FunctionComponent<IHealthcheckContainer
       // 500 - API NOT Responding
       if (axiosError?.response?.status === 500) {
         systemIssues.push({
-          key: HealthcheckMessagesTypesEnum.PIMS_API,
+          key: HealthCheckMessagesTypesEnum.PIMS_API,
           msg: pimsHealthcheckMessages[
-            HealthcheckMessagesTypesEnum[HealthcheckMessagesTypesEnum.PIMS_API]
+            HealthCheckMessagesTypesEnum[HealthCheckMessagesTypesEnum.PIMS_API]
           ],
         });
 
@@ -105,9 +129,9 @@ export const HealthcheckContainer: React.FunctionComponent<IHealthcheckContainer
       const pimsApi = await getLive();
       if (pimsApi.data.status !== 'Healthy') {
         systemIssues.push({
-          key: HealthcheckMessagesTypesEnum.PIMS_API,
+          key: HealthCheckMessagesTypesEnum.PIMS_API,
           msg: pimsHealthcheckMessages[
-            HealthcheckMessagesTypesEnum[HealthcheckMessagesTypesEnum.PIMS_API]
+            HealthCheckMessagesTypesEnum[HealthCheckMessagesTypesEnum.PIMS_API]
           ],
         });
 
diff --git a/source/frontend/src/hooks/pims-api/interfaces/IHealthcheckResponse.ts b/source/frontend/src/hooks/pims-api/interfaces/IHealthcheckResponse.ts
index ecc802fec7..402dce320f 100644
--- a/source/frontend/src/hooks/pims-api/interfaces/IHealthcheckResponse.ts
+++ b/source/frontend/src/hooks/pims-api/interfaces/IHealthcheckResponse.ts
@@ -1,8 +1,8 @@
-export interface IHealthcheckResponse {
+export interface IHealthCheckResponse {
   data: object;
   duration: Date;
   status: string;
   tags: string[];
 }
 
-export default IHealthcheckResponse;
+export default IHealthCheckResponse;
diff --git a/source/frontend/src/hooks/pims-api/interfaces/ISystemCheck.ts b/source/frontend/src/hooks/pims-api/interfaces/ISystemCheck.ts
index 7a75b44495..f2d0240222 100644
--- a/source/frontend/src/hooks/pims-api/interfaces/ISystemCheck.ts
+++ b/source/frontend/src/hooks/pims-api/interfaces/ISystemCheck.ts
@@ -1,4 +1,4 @@
-import IHealthcheckResponse from './IHealthcheckResponse';
+import IHealthCheckResponse from './IHealthcheckResponse';
 
 export interface ISystemCheck {
   // Status of the api.
@@ -7,12 +7,12 @@ export interface ISystemCheck {
   totalDuration: Date;
   // Dictionary of health information.
   entries: {
-    PmbcExternalApi: IHealthcheckResponse;
-    Geoserver: IHealthcheckResponse;
-    Mayan: IHealthcheckResponse;
-    Ltsa: IHealthcheckResponse;
-    Geocoder: IHealthcheckResponse;
-    Cdogs: IHealthcheckResponse;
+    PmbcExternalApi: IHealthCheckResponse;
+    Geoserver: IHealthCheckResponse;
+    Mayan: IHealthCheckResponse;
+    Ltsa: IHealthCheckResponse;
+    Geocoder: IHealthCheckResponse;
+    Cdogs: IHealthCheckResponse;
   };
 }
 
diff --git a/source/frontend/src/layouts/models/HealthcheckMessagesTypes.ts b/source/frontend/src/layouts/models/HealthcheckMessagesTypes.ts
index 607faf3501..7b9c7304f8 100644
--- a/source/frontend/src/layouts/models/HealthcheckMessagesTypes.ts
+++ b/source/frontend/src/layouts/models/HealthcheckMessagesTypes.ts
@@ -1,4 +1,4 @@
-export enum HealthcheckMessagesTypesEnum {
+export enum HealthCheckMessagesTypesEnum {
   PIMS_API = 'PIMS API',
   PMBC = 'PMBC',
   GEOSERVER = 'GEOSERVER',


Reviews:
user: login: asanchezr
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T17:56:59Z
user: login: asanchezr
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T18:00:33Z
user: login: asanchezr
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-09T18:05:06Z
user: login: eddherrera
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T18:07:01Z
user: login: eddherrera
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T18:07:10Z

Review comments:
diff_hunk: @@ -120,4 +120,11 @@ describe('Healthcheck container', () => {
 
     expect(updateHealthcheckResult).toHaveBeenCalledWith(true);
   });
+
+  it(`sets the right amount of healtcheck issues`, async () => {
+    const { } = await setup();
path: source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx
user: login: asanchezr
body: nit: no need for the empty `const {}` here - just do `await setup()`
created_at: 2025-04-09T17:56:59Z
author_association: COLLABORATOR
diff_hunk: @@ -30,39 +30,63 @@ export const HealthcheckContainer: React.FunctionComponent<IHealthcheckContainer
   const keycloak = useKeycloakWrapper();
 
   const checkExternalSystemStatus = useCallback(
-    (response: IHealthcheckResponse, service: HealthcheckMessagesTypesEnum) => {
+    (
+      response: IHealthcheckResponse,
+      service: HealthcheckMessagesTypesEnum,
+      issues: IHealthCheckIssue[],
+    ) => {
path: source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx
user: login: asanchezr
body: nit: I know this PR is mostly about fixing bugs but I see some inconsistent naming here. We should pick either "IHealthcheck..." or "IHealthCheck..." - I personally prefer the 2nd option. But regardless of which option you pick, we should use a consistent naming
created_at: 2025-04-09T18:00:33Z
author_association: COLLABORATOR
diff_hunk: @@ -30,39 +30,63 @@ export const HealthcheckContainer: React.FunctionComponent<IHealthcheckContainer
   const keycloak = useKeycloakWrapper();
 
   const checkExternalSystemStatus = useCallback(
-    (response: IHealthcheckResponse, service: HealthcheckMessagesTypesEnum) => {
+    (
+      response: IHealthcheckResponse,
+      service: HealthcheckMessagesTypesEnum,
+      issues: IHealthCheckIssue[],
+    ) => {
path: source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.tsx
user: login: eddherrera
body: updated
created_at: 2025-04-09T18:07:01Z
author_association: COLLABORATOR
diff_hunk: @@ -120,4 +120,11 @@ describe('Healthcheck container', () => {
 
     expect(updateHealthcheckResult).toHaveBeenCalledWith(true);
   });
+
+  it(`sets the right amount of healtcheck issues`, async () => {
+    const { } = await setup();
path: source/frontend/src/components/layout/Healthcheck/HealthcheckContainer.test.tsx
user: login: eddherrera
body: updated
created_at: 2025-04-09T18:07:09Z
author_association: COLLABORATOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-09T18:00:52Z
body: See CodeCov Report Here: https://app.codecov.io/github/bcgov/psp/pull/4745
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-09T18:08:28Z
body: See CodeCov Report Here: https://app.codecov.io/github/bcgov/psp/pull/4745
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-04-09T18:13:57Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=bcgov_PSP&pullRequest=4745) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=bcgov_PSP&pullRequest=4745&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=bcgov_PSP&pullRequest=4745&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=bcgov_PSP&pullRequest=4745&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=bcgov_PSP&pullRequest=4745&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=bcgov_PSP&pullRequest=4745&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=bcgov_PSP&pullRequest=4745)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-09T18:14:59Z
body: See CodeCov Report Here: https://app.codecov.io/github/bcgov/psp/pull/4745
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-09T18:23:19Z
body: See CodeCov Report Here: https://app.codecov.io/github/bcgov/psp/pull/4745
author_association: CONTRIBUTOR