Repository: DEFRA/ffc-ahwr-farmer-claim
Pull request #448: feat(AHWR-705): multi herds text updates on species numbers
Author: login: rossjarvisesynergy
Created: 2025-04-22T08:43:57Z | Merged: 2025-04-22T11:42:33Z



Diff:
diff --git a/app/routes/endemics/species-numbers.js b/app/routes/endemics/species-numbers.js
index a58c8f32..a75e9504 100644
--- a/app/routes/endemics/species-numbers.js
+++ b/app/routes/endemics/species-numbers.js
@@ -48,11 +48,18 @@ const sheepNumbersExceptionsText = {
 }
 const errorMessageText = (typeOfReview, speciesEligbileNumberForDisplay) => {
   const { isReview } = getReviewType(typeOfReview)
-  return `Select if you had ${speciesEligbileNumberForDisplay} on the date of the ${isReview ? 'review' : 'follow-up'}.`
+  const claimTypeText = isReview ? 'review' : 'follow-up'
+
+  return config.multiHerds.enabled
+    ? `Select yes if you had ${speciesEligbileNumberForDisplay} in this herd on the date of the ${claimTypeText}.`
+    : `Select if you had ${speciesEligbileNumberForDisplay} on the date of the ${claimTypeText}.`
 }
 const legendText = (speciesEligbileNumberForDisplay, typeOfReview) => {
   const { isReview } = getReviewType(typeOfReview)
-  return `Did you have ${speciesEligbileNumberForDisplay} on the date of the ${isReview ? 'review' : 'follow-up'}?`
+  const claimTypeText = isReview ? 'review' : 'follow-up'
+  const herdText = config.multiHerds.enabled ? ' in this herd' : ''
+
+  return `Did you have ${speciesEligbileNumberForDisplay}${herdText} on the date of the ${claimTypeText}?`
 }
 
 const getHandler = {
diff --git a/package-lock.json b/package-lock.json
index 8b233412..11d1b426 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "ffc-ahwr-farmer-claim",
-  "version": "2.2.4",
+  "version": "2.2.5",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "ffc-ahwr-farmer-claim",
-      "version": "2.2.4",
+      "version": "2.2.5",
       "license": "OGL-UK-3.0",
       "dependencies": {
         "@2toad/profanity": "^3.0.1",
diff --git a/package.json b/package.json
index 33d00305..03dc8f0c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ffc-ahwr-farmer-claim",
-  "version": "2.2.4",
+  "version": "2.2.5",
   "description": "Web frontend for farmer claim journey",
   "homepage": "https://github.com/DEFRA/ffc-ahwr-farmer-claim",
   "main": "app/index.js",
diff --git a/test/integration/narrow/routes/endemics/species-numbers.test.js b/test/integration/narrow/routes/endemics/species-numbers.test.js
index b6d534b9..ebb5dc37 100644
--- a/test/integration/narrow/routes/endemics/species-numbers.test.js
+++ b/test/integration/narrow/routes/endemics/species-numbers.test.js
@@ -9,6 +9,7 @@ import { getReviewType } from '../../../../../app/lib/get-review-type.js'
 import { claimConstants } from '../../../../../app/constants/claim.js'
 import { getSpeciesEligibleNumberForDisplay } from '../../../../../app/lib/display-helpers.js'
 import { isPIHuntEnabledAndVisitDateAfterGoLive } from '../../../../../app/lib/context-helper.js'
+import { config } from '../../../../../app/config/index.js'
 
 jest.mock('../../../../../app/session')
 jest.mock('../../../../../app/event/raise-invalid-data-event')
@@ -17,6 +18,10 @@ jest.mock('../../../../../app/lib/context-helper.js')
 const auth = { credentials: {}, strategy: 'cookie' }
 const url = '/claim/endemics/species-numbers'
 
+beforeEach(async () => {
+  config.multiHerds.enabled = false
+})
+
 describe('Species numbers test when Optional PI Hunt is OFF', () => {
   let server
 
@@ -58,6 +63,29 @@ describe('Species numbers test when Optional PI Hunt is OFF', () => {
       expectPhaseBanner.ok($)
     })
 
+    test.each([
+      { typeOfLivestock: 'beef', typeOfReview: 'E', reviewTestResults: 'negative' },
+      { typeOfLivestock: 'dairy', typeOfReview: 'R', reviewTestResults: 'positive' }
+    ])('returns 200 when multi herds is enabled', async ({ typeOfLivestock, typeOfReview, reviewTestResults }) => {
+      config.multiHerds.enabled = true
+      getEndemicsClaim.mockImplementation(() => ({ typeOfLivestock, typeOfReview, reviewTestResults, reference: 'TEMP-6GSE-PIR8' }))
+      const options = {
+        method: 'GET',
+        auth,
+        url
+      }
+
+      const res = await server.inject(options)
+      const $ = cheerio.load(res.payload)
+
+      expect(res.statusCode).toBe(200)
+      expect($('.govuk-fieldset__heading').text().trim()).toEqual(`Did you have 11 or more ${typeOfLivestock} cattle  in this herd on the date of the ${typeOfReview === claimConstants.claimType.review ? 'review' : 'follow-up'}?`)
+      expect($('title').text().trim()).toContain('Number - Get funding to improve animal health and welfare')
+      expect($('.govuk-hint').text().trim()).toEqual('You can find this on the summary the vet gave you.')
+      expect($('.govuk-radios__item').length).toEqual(2)
+      expectPhaseBanner.ok($)
+    })
+
     test('returns 404 when there is no claim', async () => {
       getEndemicsClaim.mockReturnValueOnce({})
       getEndemicsClaim.mockReturnValueOnce({ reference: 'TEMP-6GSE-PIR8' })
@@ -188,6 +216,27 @@ describe('Species numbers test when Optional PI Hunt is OFF', () => {
       expect($('h1').text().trim()).toMatch(`Did you have ${getSpeciesEligibleNumberForDisplay({ typeOfLivestock: 'beef' }, true)} on the date of the ${isReview ? 'review' : 'follow-up'}?`)
       expect($('#main-content > div > div > div > div > div > ul > li > a').text()).toMatch(`Select if you had ${getSpeciesEligibleNumberForDisplay({ typeOfLivestock: 'beef' }, true)} on the date of the ${isReview ? 'review' : 'follow-up'}.`)
     })
+
+    test('shows error when payload is invalid and multi herds is enabled', async () => {
+      config.multiHerds.enabled = true
+      const { isReview } = getReviewType('E')
+      getEndemicsClaim.mockImplementation(() => ({ typeOfLivestock: 'beef', reviewTestResults: 'positive' }))
+      const options = {
+        method: 'POST',
+        url,
+        auth,
+        payload: { crumb, speciesNumbers: undefined },
+        headers: { cookie: `crumb=${crumb}` }
+      }
+
+      const res = await server.inject(options)
+
+      expect(res.statusCode).toBe(400)
+      const $ = cheerio.load(res.payload)
+      expect($('h1').text().trim()).toMatch(`Did you have ${getSpeciesEligibleNumberForDisplay({ typeOfLivestock: 'beef' }, true)} in this herd on the date of the ${isReview ? 'review' : 'follow-up'}?`)
+      expect($('#main-content > div > div > div > div > div > ul > li > a').text()).toMatch(`Select yes if you had ${getSpeciesEligibleNumberForDisplay({ typeOfLivestock: 'beef' }, true)} in this herd on the date of the ${isReview ? 'review' : 'follow-up'}.`)
+    })
+
     test('redirect the user to 404 page in fail action and no claim object', async () => {
       const options = {
         method: 'POST',


Reviews:
user: login: bendef-24
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-22T10:29:44Z
user: login: bendef-24
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-04-22T10:32:13Z
user: login: RobCatton
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-22T10:33:07Z
user: login: rossjarvisesynergy
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-22T11:39:25Z
user: login: bendef-24
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-22T11:42:01Z

Review comments:
diff_hunk: @@ -95,6 +123,7 @@ describe('Species numbers test when Optional PI Hunt is OFF', () => {
 
     beforeEach(async () => {
       crumb = await getCrumbs(server)
+      config.multiHerds.enabled = false
path: test/integration/narrow/routes/endemics/species-numbers.test.js
user: login: bendef-24
body: You could put this in a file-level beforeEach to reduce duplication, but I'm happy for it to stay as-is.
created_at: 2025-04-22T10:29:43Z
author_association: COLLABORATOR
diff_hunk: @@ -95,6 +123,7 @@ describe('Species numbers test when Optional PI Hunt is OFF', () => {
 
     beforeEach(async () => {
       crumb = await getCrumbs(server)
+      config.multiHerds.enabled = false
path: test/integration/narrow/routes/endemics/species-numbers.test.js
user: login: rossjarvisesynergy
body: done

created_at: 2025-04-22T11:39:25Z
author_association: COLLABORATOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-04-22T11:31:25Z
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=ffc-ahwr-farmer-claim&pullRequest=448) **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=ffc-ahwr-farmer-claim&pullRequest=448&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=ffc-ahwr-farmer-claim&pullRequest=448&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=ffc-ahwr-farmer-claim&pullRequest=448&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [92.3% Coverage on New Code](https://sonarcloud.io/component_measures?id=ffc-ahwr-farmer-claim&pullRequest=448&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=ffc-ahwr-farmer-claim&pullRequest=448&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=ffc-ahwr-farmer-claim&pullRequest=448)


author_association: NONE