Repository: dhsc-govuk/FingertipsNext
Pull request #202: Feature/dhscft 390 inequalities tag on search results2
Author: login: MonkeyDate
Created: 2025-02-28T14:30:03Z | Merged: 2025-03-04T12:26:52Z

# Description

Jira ticket: DHSCFT-390](https://bjss-enterprise.atlassian.net/browse/DHSCFT-390)

Update frontend to show 'has inequalities' tag to any indicator known to include inequalities data.

## Changes

- Update `IndicatorsDocument` definition to expose `hasInequalities`, matching the data returned from AI Search
- If `hasInequalities` is `true` for an indicator add the appropriate tag
- Make tag row layout dynamic so there are 0-3 columns, depending on data (only 2 tags available currently)
- Small styling changes so that multiple tags layout as-per figma
- Sneaky change to correct casing of text spotted during BA review but unrelated to this actual ticket.

## Validation

Manual testing of the various tag possibilities during BA review session.


Diff:
diff --git a/frontend/fingertips-frontend/app/results/page.test.tsx b/frontend/fingertips-frontend/app/results/page.test.tsx
index f28c4a292..a1484fc7e 100644
--- a/frontend/fingertips-frontend/app/results/page.test.tsx
+++ b/frontend/fingertips-frontend/app/results/page.test.tsx
@@ -41,6 +41,7 @@ const generateIndicatorSearchResults = (id: string): IndicatorDocument => ({
   lastUpdatedDate: new Date(),
   associatedAreaCodes: [],
   unitLabel: 'some unit label',
+  hasInequalities: true,
 });
 const mockIndicatorSearchResults: IndicatorDocument[] = [
   generateIndicatorSearchResults('1'),
diff --git a/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/index.tsx b/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/index.tsx
index 4069b0646..0a15f7c2d 100644
--- a/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/index.tsx
+++ b/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/index.tsx
@@ -108,7 +108,7 @@ export function IndicatorSelectionForm({
         data-testid="search-results-button-submit"
         disabled={shouldDisableViewDataButton(searchState)}
       >
-        View Data
+        View data
       </Button>
     </form>
   );
diff --git a/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/indicatorSelectionForm.test.tsx b/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/indicatorSelectionForm.test.tsx
index bb62d0766..649bfb4ae 100644
--- a/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/indicatorSelectionForm.test.tsx
+++ b/frontend/fingertips-frontend/components/forms/IndicatorSelectionForm/indicatorSelectionForm.test.tsx
@@ -34,6 +34,7 @@ const MOCK_DATA: IndicatorDocument[] = [
     lastUpdatedDate: new Date('December 6, 2024'),
     associatedAreaCodes: [],
     unitLabel: '',
+    hasInequalities: false,
   },
   {
     indicatorID: '2',
@@ -46,6 +47,7 @@ const MOCK_DATA: IndicatorDocument[] = [
     lastUpdatedDate: new Date('November 5, 2023'),
     associatedAreaCodes: [],
     unitLabel: '',
+    hasInequalities: true,
   },
 ];
 
diff --git a/frontend/fingertips-frontend/components/molecules/result/__snapshots__/searchResult.test.tsx.snap b/frontend/fingertips-frontend/components/molecules/result/__snapshots__/searchResult.test.tsx.snap
index f4c261292..fc031c147 100644
--- a/frontend/fingertips-frontend/components/molecules/result/__snapshots__/searchResult.test.tsx.snap
+++ b/frontend/fingertips-frontend/components/molecules/result/__snapshots__/searchResult.test.tsx.snap
@@ -440,17 +440,7 @@ exports[`Indicator Checkbox snapshot test 1`] = `
             </div>
             <div
               class="c1 c12"
-            >
-              <div
-                class="c3"
-              />
-              <div
-                class="c3"
-              />
-              <div
-                class="c3"
-              />
-            </div>
+            />
           </span>
         </label>
       </div>
diff --git a/frontend/fingertips-frontend/components/molecules/result/index.tsx b/frontend/fingertips-frontend/components/molecules/result/index.tsx
index 9e05549fc..6d7498625 100644
--- a/frontend/fingertips-frontend/components/molecules/result/index.tsx
+++ b/frontend/fingertips-frontend/components/molecules/result/index.tsx
@@ -28,6 +28,10 @@ type SearchResultProps = {
   currentDate?: Date;
 };
 
+const TagsColumn = styled(GridCol)`
+  padding-right: 0px;
+`;
+
 const StyledParagraph = styled(Paragraph)(
   typography.font({ size: 19, lineHeight: '1' })
 );
@@ -123,17 +127,24 @@ export function SearchResult({
             <StyledParagraph>{`Data period: ${formatDataPeriod(result.earliestDataPeriod, result.latestDataPeriod)}`}</StyledParagraph>
             <FinalParagraph>{`Last updated: ${formatDate(result.lastUpdatedDate)}`}</FinalParagraph>
             <TagRow>
-              <GridCol>
-                {isWithinOneMonth(currentDate, result.lastUpdatedDate) ? (
+              {isWithinOneMonth(currentDate, result.lastUpdatedDate) ? (
+                <TagsColumn>
                   <GreyTag data-testid="tag-recent-indicator">
                     Updated in last month
                   </GreyTag>
-                ) : (
-                  <></>
-                )}
-              </GridCol>
-              <GridCol></GridCol>
-              <GridCol></GridCol>
+                </TagsColumn>
+              ) : (
+                <></>
+              )}
+              {result.hasInequalities ? (
+                <TagsColumn>
+                  <GreyTag data-testid="tag-has-inequalities">
+                    Contains inequality data
+                  </GreyTag>
+                </TagsColumn>
+              ) : (
+                <></>
+              )}
             </TagRow>
           </Checkbox>
         </GridCol>
diff --git a/frontend/fingertips-frontend/components/molecules/result/searchResult.test.tsx b/frontend/fingertips-frontend/components/molecules/result/searchResult.test.tsx
index 0ba0fa8fb..6171b63aa 100644
--- a/frontend/fingertips-frontend/components/molecules/result/searchResult.test.tsx
+++ b/frontend/fingertips-frontend/components/molecules/result/searchResult.test.tsx
@@ -18,6 +18,7 @@ const MOCK_DATA: IndicatorDocument[] = [
     dataSource: 'NHS website',
     lastUpdatedDate: new Date('December 6, 2024'),
     associatedAreaCodes: [],
+    hasInequalities: false,
     unitLabel: '',
   },
   {
@@ -30,10 +31,24 @@ const MOCK_DATA: IndicatorDocument[] = [
     dataSource: 'Student article',
     lastUpdatedDate: new Date('November 5, 2023'),
     associatedAreaCodes: [],
+    hasInequalities: true,
     unitLabel: '',
   },
 ];
 
+const MOCK_DATA_LASTUPDATED_INEQUALITIES: IndicatorDocument = {
+  indicatorID: '101',
+  indicatorName: 'NHS',
+  indicatorDefinition: 'Total number of patients registered with the practice',
+  earliestDataPeriod: '1999',
+  latestDataPeriod: '2023',
+  dataSource: 'NHS website',
+  lastUpdatedDate: new Date('December 6, 2024'),
+  associatedAreaCodes: [],
+  hasInequalities: true,
+  unitLabel: '',
+};
+
 const mockHandleClick = jest.fn();
 
 const initialSearchState: SearchStateParams = {
@@ -118,6 +133,60 @@ describe('content', () => {
     expect(screen.queryByText('Updated in last month')).not.toBeInTheDocument();
   });
 
+  it('should display tag if inequalities data present for indicator', () => {
+    const currentDate = new Date(MOCK_DATA[0].lastUpdatedDate);
+    render(
+      <SearchResult
+        result={MOCK_DATA[1]}
+        searchState={initialSearchState}
+        handleClick={mockHandleClick}
+        currentDate={currentDate}
+      />
+    );
+    expect(screen.queryByText('Contains inequality data')).toBeInTheDocument();
+  });
+
+  it('should NOT display tag if inequalities data NOT present for indicator', () => {
+    const currentDate = new Date(MOCK_DATA[0].lastUpdatedDate);
+    render(
+      <SearchResult
+        result={MOCK_DATA[0]}
+        searchState={initialSearchState}
+        handleClick={mockHandleClick}
+        currentDate={currentDate}
+      />
+    );
+    expect(
+      screen.queryByText('Contains inequality data')
+    ).not.toBeInTheDocument();
+  });
+
+  it('should show LAST UPDATE tag then INEQUALITIES tag (left to right) if both present in data', () => {
+    const currentDate = new Date(
+      MOCK_DATA_LASTUPDATED_INEQUALITIES.lastUpdatedDate
+    );
+    render(
+      <SearchResult
+        result={MOCK_DATA_LASTUPDATED_INEQUALITIES}
+        searchState={initialSearchState}
+        handleClick={mockHandleClick}
+        currentDate={currentDate}
+      />
+    );
+
+    const lastUpdatedElement = screen.queryByText('Updated in last month');
+    const inequalitiesElement = screen.queryByText('Contains inequality data');
+
+    expect(lastUpdatedElement).toBeInTheDocument();
+    expect(inequalitiesElement).toBeInTheDocument();
+
+    if (lastUpdatedElement && inequalitiesElement)
+      // IF should always be true but check keeps the various tools happy
+      expect(
+        lastUpdatedElement.compareDocumentPosition(inequalitiesElement)
+      ).toBe(Node.DOCUMENT_POSITION_FOLLOWING);
+  });
+
   it('should display a range of dates if earliest data period and latest data period are different', () => {
     render(
       <SearchResult
diff --git a/frontend/fingertips-frontend/components/pages/results/Results.test.tsx b/frontend/fingertips-frontend/components/pages/results/Results.test.tsx
index 770e3ae35..6ee4534c5 100644
--- a/frontend/fingertips-frontend/components/pages/results/Results.test.tsx
+++ b/frontend/fingertips-frontend/components/pages/results/Results.test.tsx
@@ -50,6 +50,7 @@ const MOCK_DATA: IndicatorDocument[] = [
     lastUpdatedDate: new Date('December 6, 2024'),
     associatedAreaCodes: [],
     unitLabel: '',
+    hasInequalities: false,
   },
   {
     indicatorID: '2',
@@ -62,6 +63,7 @@ const MOCK_DATA: IndicatorDocument[] = [
     lastUpdatedDate: new Date('November 5, 2023'),
     associatedAreaCodes: [],
     unitLabel: '',
+    hasInequalities: true,
   },
 ];
 const searchedIndicator = 'test';
diff --git a/frontend/fingertips-frontend/lib/search/indicatorSearchServiceMock.test.ts b/frontend/fingertips-frontend/lib/search/indicatorSearchServiceMock.test.ts
index fb39e0c23..7977242b8 100644
--- a/frontend/fingertips-frontend/lib/search/indicatorSearchServiceMock.test.ts
+++ b/frontend/fingertips-frontend/lib/search/indicatorSearchServiceMock.test.ts
@@ -14,6 +14,7 @@ describe('IndicatorSearchServiceMock', () => {
       lastUpdatedDate: new Date('December 6, 2024'),
       associatedAreaCodes: ['Area1'],
       unitLabel: '',
+      hasInequalities: false,
     },
     {
       indicatorID: '2',
@@ -25,6 +26,7 @@ describe('IndicatorSearchServiceMock', () => {
       lastUpdatedDate: new Date('November 5, 2023'),
       associatedAreaCodes: ['Area1', 'Area2'],
       unitLabel: '',
+      hasInequalities: true,
     },
   ];
   let indicatorSearchMock: IIndicatorSearchService;
diff --git a/frontend/fingertips-frontend/lib/search/searchTypes.ts b/frontend/fingertips-frontend/lib/search/searchTypes.ts
index cfebfe94e..74a60137f 100644
--- a/frontend/fingertips-frontend/lib/search/searchTypes.ts
+++ b/frontend/fingertips-frontend/lib/search/searchTypes.ts
@@ -18,6 +18,7 @@ export type IndicatorDocument = {
   latestDataPeriod: string; // Newest value held in database column 'Year'.
   lastUpdatedDate: Date;
   associatedAreaCodes: string[];
+  hasInequalities: boolean;
   unitLabel: string;
 };
 


Reviews:
user: login: Joe-Hendley
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T13:25:46Z
user: login: MonkeyDate
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T14:31:36Z
user: login: dlzhry2
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:15:20Z
user: login: dlzhry2
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:22:04Z
user: login: MonkeyDate
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:28:13Z

Review comments:
diff_hunk: @@ -123,17 +127,22 @@ export function SearchResult({
             <StyledParagraph>{`Data period: ${formatDataPeriod(result.earliestDataPeriod, result.latestDataPeriod)}`}</StyledParagraph>
             <FinalParagraph>{`Last updated: ${formatDate(result.lastUpdatedDate)}`}</FinalParagraph>
             <TagRow>
-              <GridCol>
path: frontend/fingertips-frontend/components/molecules/result/index.tsx
user: login: Joe-Hendley
body: My understanding was that we were to have the tags in 3 columns - has this changed?
created_at: 2025-03-03T13:25:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -123,17 +127,22 @@ export function SearchResult({
             <StyledParagraph>{`Data period: ${formatDataPeriod(result.earliestDataPeriod, result.latestDataPeriod)}`}</StyledParagraph>
             <FinalParagraph>{`Last updated: ${formatDate(result.lastUpdatedDate)}`}</FinalParagraph>
             <TagRow>
-              <GridCol>
path: frontend/fingertips-frontend/components/molecules/result/index.tsx
user: login: MonkeyDate
body: No. There will be up to 3 tags. I changed the code so the columns only exist if there is a tag to go inside them.
created_at: 2025-03-03T14:31:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+<component name="ProjectRunConfigurationManager">
path: frontend/fingertips-frontend/.run/All Tests.run.xml
user: login: dlzhry2
body: This file plus the other 2 in the `frontend/fingertips-frontend/.run/` directory are appearing in the Git diff. Is this something to do with how you're running tests locally, or is this a change we want for everyone in the repo.

If it isn't could be worth putting the .run dir into git ignore. 
created_at: 2025-03-03T17:15:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+<component name="ProjectRunConfigurationManager">
path: frontend/fingertips-frontend/.run/All Tests.run.xml
user: login: MonkeyDate
body: I'm not sure if we have an official view on this...... They are for Jetbrains specific IDEs. I'll ask the higher-ups
created_at: 2025-03-03T17:28:12Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-04T09:47:42Z
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=dhsc-govuk_FingertipsNext&pullRequest=202) **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=dhsc-govuk_FingertipsNext&pullRequest=202&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=dhsc-govuk_FingertipsNext&pullRequest=202&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=dhsc-govuk_FingertipsNext&pullRequest=202&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=dhsc-govuk_FingertipsNext&pullRequest=202&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [4.3% Duplication on New Code](https://sonarcloud.io/component_measures?id=dhsc-govuk_FingertipsNext&pullRequest=202&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=dhsc-govuk_FingertipsNext&pullRequest=202)


author_association: NONE