diff --git a/package-lock.json b/package-lock.json
index cd1faabe0..e3385483a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "flood-app",
- "version": "8.4.0",
+ "version": "8.5.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "flood-app",
- "version": "8.4.0",
+ "version": "8.5.0",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
@@ -72,7 +72,7 @@
"husky": "^8.0.3",
"jsdom": "^22.1.0",
"mockdate": "^3.0.5",
- "node-html-parser": "^6.1.11",
+ "node-html-parser": "^6.1.13",
"nodemon": "^3.0.1",
"proxyquire": "^2.1.3"
},
@@ -8791,9 +8791,9 @@
}
},
"node_modules/node-html-parser": {
- "version": "6.1.12",
- "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.12.tgz",
- "integrity": "sha512-/bT/Ncmv+fbMGX96XG9g05vFt43m/+SYKIs9oAemQVYyVcZmDAI2Xq/SbNcpOA35eF0Zk2av3Ksf+Xk8Vt8abA==",
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
+ "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
"dev": true,
"dependencies": {
"css-select": "^5.1.0",
diff --git a/package.json b/package.json
index b65dcce5f..96ee182e3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "flood-app",
- "version": "8.4.0",
+ "version": "8.5.0",
"description": "Flood risk app",
"main": "index.js",
"repository": "github:defra/flood-app",
@@ -96,7 +96,7 @@
"husky": "^8.0.3",
"jsdom": "^22.1.0",
"mockdate": "^3.0.5",
- "node-html-parser": "^6.1.11",
+ "node-html-parser": "^6.1.13",
"nodemon": "^3.0.1",
"proxyquire": "^2.1.3"
}
diff --git a/release-docs/CFF-8.5.0.md b/release-docs/CFF-8.5.0.md
new file mode 100644
index 000000000..fa1fb41fe
--- /dev/null
+++ b/release-docs/CFF-8.5.0.md
@@ -0,0 +1,28 @@
+# Check For Flooding Release
+
+* Version: 8.5.0
+* Proposed Release Date: 17th July 2024
+* Jira Release Overview: https://eaflood.atlassian.net/projects/FSR/versions/17136/tab/release-report-all-issues
+
+
+## Tickets
+
+
+
+ * FSR-1208 | river and sea levels search redirects (#723)
+
+ * FSR-1207 | update page title to use place name
+
+
+
+## Instructions
+
+
+ 1 - Execute LFW_{STAGE}_04_UPDATE_FLOOD_APP_AND_SERVICE_PIPELINE
+
+
+Execute smoke tests and forward results
+
+## Related Infrastructure Changes Required
+
+* None
diff --git a/server/models/views/alerts-and-warnings.js b/server/models/views/alerts-and-warnings.js
index 65ef129d3..0a109a20f 100644
--- a/server/models/views/alerts-and-warnings.js
+++ b/server/models/views/alerts-and-warnings.js
@@ -2,36 +2,39 @@ const { bingKeyMaps } = require('../../config')
const config = require('../../config')
class ViewModel {
- constructor ({ location, place, floods, station, error }) {
+ constructor ({ q, location, place, floods = [], station, canonical, error }) {
Object.assign(this, {
- q: location,
+ q,
+ station,
map: station ? 'map-station' : 'map',
- station: station || null,
- placeName: place ? place.name : '',
- placeBbox: place ? place.bbox2k : [],
- placeCentre: place ? place.center : [],
+ placeName: place?.name || '',
+ placeBbox: place?.bbox2k || [],
+ placeCentre: place?.center || [],
timestamp: Date.now(),
- error: error ? true : null,
+ metaCanonical: canonical,
+ canonicalUrl: canonical,
+ error: !!error,
displayGetWarningsLink: true,
displayLongTermLink: true,
- isEngland: place ? place.isEngland.is_england : null,
- isDummyData: floods ? floods.isDummyData : false,
+ isEngland: place?.isEngland?.is_england,
+ isDummyData: floods?.isDummyData,
floodRiskUrl: config.floodRiskUrl
})
+ if (this.station && this.station.agency_name) {
+ this.pageTitle = `${this.station.agency_name} - flood alerts and warnings`
+ } else {
+ const pageTitle = place?.name ?? location
+
+ this.pageTitle = `${pageTitle ? pageTitle + ' - f' : 'F'}lood alerts and warnings`
+ }
+
if (error) {
this.pageTitle = 'Sorry, there is currently a problem searching a location'
- } else {
- if (this.station && this.station.agency_name) {
- this.pageTitle = `${this.station.agency_name} - flood alerts and warnings`
- } else {
- this.pageTitle = `${location ? location + ' - f' : 'F'}lood alerts and warnings`
- }
}
- this.countFloods = floods ? floods.floods.length : 0
- this.floods = floods
- ? floods.groups.map(item => item)
- : []
+
+ this.countFloods = floods?.floods?.length ?? 0
+ this.floods = floods?.groups?.map(item => item)
this.expose = {
station: this.station,
diff --git a/server/models/views/river-and-sea-levels.js b/server/models/views/river-and-sea-levels.js
index dc100de3b..6579a4437 100644
--- a/server/models/views/river-and-sea-levels.js
+++ b/server/models/views/river-and-sea-levels.js
@@ -112,7 +112,7 @@ function referencedStationViewModel (referencePoint, stations) {
}
}
-function placeViewModel ({ location, place, stations = [], queryGroup }) {
+function placeViewModel ({ location, place, stations = [], queryGroup, canonical, q }) {
let distStatement, title, description
const isEngland = place ? place.isEngland.is_england : true
@@ -128,10 +128,10 @@ function placeViewModel ({ location, place, stations = [], queryGroup }) {
deleteUndefinedProperties(stations)
if (location && isEngland) {
- title = `${location} - ${pageTitle}`
+ title = `${place.name ?? location} - ${pageTitle}`
description = `Find river, sea, groundwater and rainfall levels in ${location}. Check the last updated height, trend and state recorded by the measuring station.`
} else {
- title = location ? `${location} - ${pageTitle}` : pageTitle
+ title = place ? `${place.name} - ${pageTitle}` : pageTitle
description = metaDescription
}
@@ -141,13 +141,15 @@ function placeViewModel ({ location, place, stations = [], queryGroup }) {
filters,
floodRiskUrl,
distStatement,
- q: location,
+ q: q || location,
clientModel: getClientModel(isEngland ? place.bbox10k : []),
queryGroup: activeFilter,
placeAddress: place.address,
...getDataJourneyClickStrings(),
pageTitle: title,
- metaDescription: description
+ metaDescription: description,
+ metaCanonical: canonical,
+ canonicalUrl: canonical
}
}
diff --git a/server/routes/alerts-and-warnings.js b/server/routes/alerts-and-warnings.js
index f371f2b6c..66557dc37 100644
--- a/server/routes/alerts-and-warnings.js
+++ b/server/routes/alerts-and-warnings.js
@@ -3,90 +3,160 @@ const ViewModel = require('../models/views/alerts-and-warnings')
const Floods = require('../models/floods')
const locationService = require('../services/location')
const util = require('../util')
+const {
+ slugify,
+ isLocationEngland,
+ isValidLocationSlug,
+ isPlaceEngland,
+ failActionHandler,
+ renderNotFound,
+ renderLocationNotFound,
+ createQueryParametersString
+} = require('./lib/utils')
+
+const route = 'alerts-and-warnings'
+const QUERY_STRING_LOCATION_MAX_LENGTH = 200
+
+async function routeHandler (request, h) {
+ let location = request.query.q || request.payload?.location
+
+ location = util.cleanseLocation(location)
+
+ request.yar.set('q', { location })
+
+ const direction = request.query.direction === 'downstream' ? 'd' : 'u'
+
+ let model, floods
+
+ if (request.query.station) {
+ const station = await request.server.methods.flood.getStationById(request.query.station, direction)
+ const warningsAlerts = await request.server.methods.flood.getWarningsAlertsWithinStationBuffer(station.rloi_id)
+
+ floods = new Floods({ floods: warningsAlerts })
+ model = new ViewModel({ location, floods, station })
+ return h.view(route, { model })
+ }
+
+ if (!location) {
+ const data = await request.server.methods.flood.getFloods()
+ floods = new Floods(data)
+ model = new ViewModel({ location, floods })
+ return h.view(route, { model })
+ }
+
+ if (isLocationEngland(location)) {
+ return h.redirect(`/${route}`)
+ }
+
+ const [place] = await locationService.find(location)
+
+ if (!place) {
+ if (request.method === 'get') {
+ return renderNotFound(location)
+ }
+
+ return renderLocationNotFound(route, location, h)
+ }
+
+ if (!isPlaceEngland(place)) {
+ request.logger.warn({
+ situation: 'Location search error: Valid response but location not in England.'
+ })
+
+ if (request.method === 'post') {
+ return renderLocationNotFound(route, location, h)
+ }
+ }
+
+ const queryString = createQueryParametersString(request.query)
+
+ return h.redirect(`/${route}/${slugify(place?.name)}${queryString}`).permanent()
+}
+
+async function locationRouteHandler (request, h) {
+ const canonicalUrl = request.url.origin + request.url.pathname
+ const location = util.cleanseLocation(request.params.location)
+
+ const [place] = await locationService.find(location)
+
+ if (isLocationEngland(location)) {
+ return h.redirect(`/${route}`)
+ }
+
+ if (!isValidLocationSlug(location, place)) {
+ return renderNotFound(location)
+ }
+
+ if (!isPlaceEngland(place)) {
+ request.logger.warn({
+ situation: 'Location search error: Valid response but location not in England.'
+ })
+
+ return renderNotFound(location)
+ }
+
+ // Data passed to floods model so the schema is the same as cached floods
+ const data = await request.server.methods.flood.getFloodsWithin(place.bbox2k)
+ const floods = new Floods(data)
+ const model = new ViewModel({ location, place, floods, canonical: canonicalUrl, q: request.yar.get('q')?.location })
+ request.yar.set('q', null)
+ return h.view(route, { model })
+}
module.exports = [{
method: 'GET',
- path: '/alerts-and-warnings',
- handler: async (request, h) => {
- const { q: location } = request.query
- let model, place, floods
-
- const direction = request.query.direction === 'downstream' ? 'd' : 'u'
- const station = request.query.station
- ? await request.server.methods.flood.getStationById(request.query.station, direction)
- : null
-
- if (station) {
- const warningsAlerts = await request.server.methods.flood.getWarningsAlertsWithinStationBuffer(station.rloi_id)
- floods = new Floods({ floods: warningsAlerts })
- model = new ViewModel({ location, place, floods, station })
- return h.view('alerts-and-warnings', { model })
- } else if (typeof location === 'undefined' || location === '' || location.match(/^england$/i)) {
- floods = new Floods(await request.server.methods.flood.getFloods())
- model = new ViewModel({ location, place, floods, station })
- return h.view('alerts-and-warnings', { model })
- } else {
- try {
- [place] = await locationService.find(util.cleanseLocation(location))
- } catch (error) {
- request.logger.warn({
- situation: `Location search error: [${error.name}] [${error.message}]`,
- err: error
- })
- const floods = new Floods(await request.server.methods.flood.getFloods())
- model = new ViewModel({ location, place, floods, station, error })
- return h.view('alerts-and-warnings', { model })
- }
-
- if (!place) {
- model = new ViewModel({ location, place, floods, station })
- return h.view('alerts-and-warnings', { model })
- }
-
- if (!place?.isEngland.is_england) {
- // If no place return empty floods
- model = new ViewModel({ location, place, floods, station })
- return h.view('alerts-and-warnings', { model })
- } else {
- // Data passed to floods model so the schema is the same as cached floods
- const data = await request.server.methods.flood.getFloodsWithin(place.bbox2k)
- floods = new Floods(data)
- model = new ViewModel({ location, place, floods, station })
- return h.view('alerts-and-warnings', { model })
- }
+ path: `/${route}`,
+ handler: routeHandler,
+ options: {
+ validate: {
+ query: joi.object({
+ q: joi.string().trim().max(QUERY_STRING_LOCATION_MAX_LENGTH),
+ station: joi.string(),
+ btn: joi.string(),
+ ext: joi.string(),
+ fid: joi.string(),
+ lyr: joi.string(),
+ v: joi.string()
+ }),
+ failAction: (request, h) => failActionHandler(request, h, route)
}
- },
+ }
+},
+{
+ method: 'GET',
+ path: `/${route}/{location}`,
+ handler: locationRouteHandler,
options: {
validate: {
+ params: joi.object({
+ location: joi.string().lowercase()
+ }),
query: joi.object({
- q: joi.string().allow('').trim().max(200),
station: joi.string(),
btn: joi.string(),
ext: joi.string(),
fid: joi.string(),
lyr: joi.string(),
v: joi.string()
- })
+ }),
+ failAction: (request, h) => failActionHandler(request, h, route)
}
}
-}, {
+},
+{
method: 'POST',
- path: '/alerts-and-warnings',
- handler: async (request, h) => {
- const { location } = request.payload
- if (location === '') {
- return h.redirect(`/alerts-and-warnings?q=${location}`)
- }
- return h.redirect(`/alerts-and-warnings?q=${encodeURIComponent(util.cleanseLocation(location))}`)
- },
+ path: `/${route}`,
+ handler: routeHandler,
options: {
validate: {
payload: joi.object({
- location: joi.string().allow('').trim().max(200).required()
+ location: joi.string()
+ .allow('')
+ .trim()
+ .max(QUERY_STRING_LOCATION_MAX_LENGTH)
+ .required()
}),
- failAction: (request, h, _err) => {
- return h.view('alerts-and-warnings').takeover()
- }
+ failAction: (request, h) => failActionHandler(request, h, route)
}
}
}]
diff --git a/server/routes/lib/utils.js b/server/routes/lib/utils.js
index 0fb99ff6b..5dac60f57 100644
--- a/server/routes/lib/utils.js
+++ b/server/routes/lib/utils.js
@@ -1,7 +1,57 @@
+const qs = require('qs')
+const boom = require('@hapi/boom')
+
function slugify (text = '') {
return text.replace(/,/g, '').replace(/ /g, '-').toLowerCase()
}
+function isLocationEngland (location) {
+ return location.match(/^england$/i)
+}
+
+function isPlaceEngland (place) {
+ return place?.isEngland.is_england
+}
+
+function isValidLocationSlug (location, place) {
+ return slugify(place?.name) === location
+}
+
+function createQueryParametersString (queryObject) {
+ const { q, location, ...otherParameters } = queryObject
+ const queryString = qs.stringify(otherParameters, { addQueryPrefix: true, encode: false })
+ return queryString
+}
+
+function renderLocationNotFound (href, location, h) {
+ return h.view('location-not-found', { pageTitle: 'Error: Find location - Check for flooding', href, location }).takeover()
+}
+
+function renderNotFound (location) {
+ return boom.notFound(`Location ${location} not found`)
+}
+
+function failActionHandler (request, h, page) {
+ request.logger.warn({
+ situation: 'Location search error: Invalid or no string input.'
+ })
+
+ const location = request.query.q || request.payload?.location
+
+ if (!location) {
+ return h.redirect(page).takeover()
+ } else {
+ return renderLocationNotFound(page, location, h)
+ }
+}
+
module.exports = {
- slugify
+ slugify,
+ failActionHandler,
+ isLocationEngland,
+ isPlaceEngland,
+ isValidLocationSlug,
+ renderNotFound,
+ renderLocationNotFound,
+ createQueryParametersString
}
diff --git a/server/routes/river-and-sea-levels.js b/server/routes/river-and-sea-levels.js
index 6c0dff8d3..46af2b90e 100644
--- a/server/routes/river-and-sea-levels.js
+++ b/server/routes/river-and-sea-levels.js
@@ -12,14 +12,109 @@ const {
} = require('../models/views/river-and-sea-levels')
const locationService = require('../services/location')
const util = require('../util')
+const {
+ slugify,
+ failActionHandler,
+ renderNotFound,
+ renderLocationNotFound,
+ createQueryParametersString,
+ isValidLocationSlug,
+ isLocationEngland,
+ isPlaceEngland
+} = require('./lib/utils')
const route = 'river-and-sea-levels'
+const QUERY_STRING_LOCATION_MAX_LENGTH = 200
const miles = 1609.344
const joiValidationQMax = 200
const joiValidationGroupMax = 11
const joiValidationSearchTypeMax = 11
+async function locationRouteHandler (request, h) {
+ const referer = request.headers.referer
+ const queryGroup = request.query.group
+
+ const canonicalUrl = request.url.origin + request.url.pathname
+ const location = util.cleanseLocation(request.params.location)
+
+ const [place] = await locationService.find(location)
+
+ if (isLocationEngland(location)) {
+ return h.redirect(`/${route}`)
+ } else if (!isValidLocationSlug(location, place)) {
+ return renderNotFound(location)
+ } else if (!isPlaceEngland(place)) {
+ request.logger.warn({
+ situation: 'Location search error: Valid response but location not in England.'
+ })
+ return renderNotFound(location)
+ } else {
+ const stations = await request.server.methods.flood.getStationsWithin(place.bbox10k)
+ const model = placeViewModel({ location, place, stations, referer, queryGroup, canonical: canonicalUrl, q: request.yar.get('q')?.location })
+ request.yar.set('q', null)
+ return h.view(route, { model })
+ }
+}
+
+async function locationQueryHandler (request, h) {
+ let location = request.query.q || request.payload?.location
+
+ location = util.cleanseLocation(location)
+
+ request.yar.set('q', { location })
+
+ if (!location) {
+ return h.view(route, { model: emptyResultsModel() })
+ }
+
+ if (isLocationEngland(location)) {
+ return h.redirect(`/${route}`)
+ }
+
+ const rivers = await request.server.methods.flood.getRiversByName(location)
+ const places = await findPlaces(location)
+
+ if (places.length + rivers.length > 1) {
+ return h.view(`${route}-list`, { model: disambiguationModel(location, places, rivers) })
+ }
+
+ if (places.length === 0) {
+ if (rivers.length === 0) {
+ if (request.method === 'get') {
+ return renderNotFound(location)
+ }
+
+ return renderLocationNotFound(route, location, h)
+ }
+
+ return h.redirect(`/${route}/river/${rivers[0].id}`)
+ }
+
+ const place = places[0]
+
+ if (!isPlaceEngland(place)) {
+ request.logger.warn({
+ situation: 'Location search error: Valid response but location not in England.'
+ })
+
+ if (request.method === 'post') {
+ return renderLocationNotFound(route, location, h)
+ }
+ }
+
+ const queryString = createQueryParametersString(request.query)
+
+ return h.redirect(`/${route}/${slugify(place?.name)}${queryString}`).permanent()
+}
+
+async function findPlaces (location) {
+ // NOTE: at the moment locationService.find just returns a single place
+ // using the [] for no results and with a nod to upcoming work to return >1 result
+ const [place] = await locationService.find(location)
+ return place ? [place] : []
+}
+
module.exports = [{
method: 'GET',
path: `/${route}/target-area/{targetAreaCode}`,
@@ -134,82 +229,48 @@ module.exports = [{
q: joi.string().trim().max(joiValidationQMax),
group: joi.string().trim().max(joiValidationGroupMax),
searchType: joi.string().trim().max(joiValidationSearchTypeMax),
- includeTypes: joi.string().default('place,river'),
'rloi-id': joi.string(),
'rainfall-id': joi.string(),
'target-area': joi.string(),
riverId: joi.string()
}),
- failAction: (request, h) => {
- request.logger.warn({
- situation: 'River and Sea levels search error: Invalid or no string input.'
- })
-
- return h.redirect()
- }
+ failAction: (request, h) => failActionHandler(request, h, route)
+ }
+ }
+}, {
+ method: 'GET',
+ path: `/${route}/{location}`,
+ handler: locationRouteHandler,
+ options: {
+ validate: {
+ params: joi.object({
+ location: joi.string().lowercase()
+ }),
+ query: joi.object({
+ group: joi.string().trim().max(joiValidationGroupMax),
+ searchType: joi.string().trim().max(joiValidationSearchTypeMax),
+ 'rloi-id': joi.string(),
+ 'rainfall-id': joi.string(),
+ 'target-area': joi.string(),
+ riverId: joi.string()
+ }),
+ failAction: (request, h) => failActionHandler(request, h, route)
}
}
}, {
method: 'POST',
path: `/${route}`,
- handler: async (request, h) => {
- const { location } = request.payload
- return h.redirect(`/${route}?q=${encodeURIComponent(location)}`).takeover()
- },
+ handler: locationQueryHandler,
options: {
validate: {
payload: joi.object({
location: joi.string()
+ .allow('')
.trim()
- .regex(new RegExp(`^[${util.ALLOWED_SEARCH_CHARS}]*$`)).required()
+ .max(QUERY_STRING_LOCATION_MAX_LENGTH)
+ .required()
}),
- failAction: (_request, h, _err) => h.view(route, { model: emptyResultsModel(_request.payload?.location.trim()) }).takeover()
+ failAction: (request, h) => failActionHandler(request, h, route)
}
}
}]
-
-async function locationQueryHandler (request, h) {
- const location = request.query.q
- const referer = request.headers.referer
- const includeTypes = request.query.includeTypes.split(',')
- const queryGroup = request.query.group
-
- let rivers = []
- let places = []
- const cleanLocation = util.cleanseLocation(location)
- if (cleanLocation && cleanLocation.length > 1 && !cleanLocation.match(/^england$/i)) {
- if (includeTypes.includes('place')) {
- places = await findPlaces(cleanLocation)
- }
- if (includeTypes.includes('river')) {
- rivers = await request.server.methods.flood.getRiversByName(cleanLocation)
- }
- }
-
- if (places.length === 0) {
- if (rivers.length === 0) {
- return h.view(route, { model: emptyResultsModel(location) })
- }
- if (rivers.length === 1) {
- return h.redirect(`/${route}/river/${rivers[0].id}`)
- }
- }
-
- if (places.length + rivers.length > 1) {
- return h.view(`${route}-list`, { model: disambiguationModel(location, places, rivers) })
- }
-
- const place = places[0]
- const stations = await request.server.methods.flood.getStationsWithin(place.bbox10k)
- const model = placeViewModel({ location, place, stations, referer, queryGroup })
- return h.view(route, { model })
-}
-
-const inUk = place => place?.isUK && !place?.isScotlandOrNorthernIreland
-
-async function findPlaces (location) {
- // NOTE: at the moment locationService.find just returns a single place
- // using the [] for no results and with a nod to upcoming work to return >1 result
- const [place] = await locationService.find(location)
- return inUk(place) ? [place] : []
-}
diff --git a/server/services/lib/bing-results-parser.js b/server/services/lib/bing-results-parser.js
index 6f6f7ad55..441023941 100644
--- a/server/services/lib/bing-results-parser.js
+++ b/server/services/lib/bing-results-parser.js
@@ -8,7 +8,7 @@ async function bingResultsParser (bingData, getIsEngland) {
const allowedConfidences = ['medium', 'high']
const allowedTypes = [
- 'populatedplace', 'postcode1', 'postcode3', 'admindivision2', 'neighborhood'
+ 'populatedplace', 'postcode1', 'postcode3', 'admindivision2', 'neighborhood', 'religiousstructure', 'roadblock'
]
const data = set.resources
.filter(r => allowedConfidences.includes(r.confidence.toLowerCase()))
diff --git a/server/views/layout.html b/server/views/layout.html
index f9e35eb87..60dada24d 100644
--- a/server/views/layout.html
+++ b/server/views/layout.html
@@ -30,7 +30,7 @@
{% if metaCanonical %}
-
+
{% endif %}
" }
+ url: '/alerts-and-warnings',
+ payload: {
+ location: ''
+ }
}
const response = await server.inject(options)
- Code.expect(response.statusCode).to.equal(200)
- const root = parse(response.payload)
- const headers = root.querySelectorAll('h2')
- Code.expect(headers.some(h => h.text.trim().startsWith("No results for \x3Cscript>alert('TEST')\x3C/script>"))).to.be.false()
+ Code.expect(response.statusCode).to.equal(404)
+ Code.expect(response.result.message).to.equal('Not Found')
})
+
lab.experiment('RLOI', () => {
lab.test('GET /river-and-sea-levels?rloi-id=7224 should redirect', async () => {
- const floodService = require('../../server/services/flood')
-
- const fakeStationsData = () => data.stationsWithinRadius
-
- const originalStation = () => data.riverStation7224
- const cachedStation = () => data.cachedStation
-
- sandbox.stub(floodService, 'getStationsByRadius').callsFake(fakeStationsData)
- sandbox.stub(floodService, 'getStationById').callsFake(originalStation)
- sandbox.stub(floodService, 'getStationsGeoJson').callsFake(cachedStation)
+ stubs.getJson.callsFake(() => data.warringtonGetJson)
+ stubs.getStationsByRadius.callsFake(() => data.stationsWithinRadius)
+ stubs.getStationById.callsFake(() => data.riverStation7224)
+ stubs.getStationsGeoJson.callsFake(() => data.cachedStation)
+ stubs.getIsEngland.callsFake(() => ({ is_england: true }))
// Set cached stationsGeojson
-
+ const floodService = require('../../server/services/flood')
floodService.stationsGeojson = await floodService.getStationsGeoJson()
- const riversPlugin = {
- plugin: {
- name: 'rivers',
- register: (server, options) => {
- server.route(require('../../server/routes/river-and-sea-levels'))
- }
- }
- }
-
- await server.register(require('../../server/plugins/views'))
- await server.register(require('../../server/plugins/session'))
- await server.register(riversPlugin)
- // Add Cache methods to server
- const registerServerMethods = require('../../server/services/server-methods')
- registerServerMethods(server)
-
- await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels?rloi-id=7224'
@@ -2640,39 +940,18 @@ lab.experiment('Test - /river-and-sea-levels', () => {
Code.expect(response.statusCode).to.equal(302)
Code.expect(response.headers.location).to.equal('/river-and-sea-levels/rloi/7224')
})
- lab.test('GET /river-and-sea-levels/rloi/7224', async () => {
- const floodService = require('../../server/services/flood')
-
- const fakeStationsData = () => data.stationsWithinRadius
- const originalStation = () => data.riverStation7224
- const cachedStation = () => data.cachedStation
-
- sandbox.stub(floodService, 'getStationsByRadius').callsFake(fakeStationsData)
- sandbox.stub(floodService, 'getStationById').callsFake(originalStation)
- sandbox.stub(floodService, 'getStationsGeoJson').callsFake(cachedStation)
+ lab.test('GET /river-and-sea-levels/rloi/7224', async () => {
+ stubs.getJson.callsFake(() => data.warringtonGetJson)
+ stubs.getStationsByRadius.callsFake(() => data.stationsWithinRadius)
+ stubs.getStationById.callsFake(() => data.riverStation7224)
+ stubs.getStationsGeoJson.callsFake(() => data.cachedStation)
+ stubs.getIsEngland.callsFake(() => ({ is_england: true }))
// Set cached stationsGeojson
-
+ const floodService = require('../../server/services/flood')
floodService.stationsGeojson = await floodService.getStationsGeoJson()
- const riversPlugin = {
- plugin: {
- name: 'rivers',
- register: (server, options) => {
- server.route(require('../../server/routes/river-and-sea-levels'))
- }
- }
- }
-
- await server.register(require('../../server/plugins/views'))
- await server.register(require('../../server/plugins/session'))
- await server.register(riversPlugin)
- // Add Cache methods to server
- const registerServerMethods = require('../../server/services/server-methods')
- registerServerMethods(server)
-
- await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels/rloi/7224'
@@ -2686,40 +965,19 @@ lab.experiment('Test - /river-and-sea-levels', () => {
Code.expect(response.payload).to.contain('Showing levels within 5 miles of Grants Bridge.')
})
})
+
lab.experiment('River', () => {
lab.test('GET /river-and-sea-levels?river-id=river-nidd should redirect', async () => {
- const floodService = require('../../server/services/flood')
-
- const fakeStationsData = () => data.stationsWithinRadius
-
- const originalStation = () => data.riverStation7224
- const cachedStation = () => data.cachedStation
-
- sandbox.stub(floodService, 'getStationsByRadius').callsFake(fakeStationsData)
- sandbox.stub(floodService, 'getStationById').callsFake(originalStation)
- sandbox.stub(floodService, 'getStationsGeoJson').callsFake(cachedStation)
+ stubs.getJson.callsFake(() => data.warringtonGetJson)
+ stubs.getStationsByRadius.callsFake(() => data.stationsWithinRadius)
+ stubs.getStationById.callsFake(() => data.riverStation7224)
+ stubs.getStationsGeoJson.callsFake(() => data.cachedStation)
+ stubs.getIsEngland.callsFake(() => ({ is_england: true }))
// Set cached stationsGeojson
-
+ const floodService = require('../../server/services/flood')
floodService.stationsGeojson = await floodService.getStationsGeoJson()
- const riversPlugin = {
- plugin: {
- name: 'rivers',
- register: (server, options) => {
- server.route(require('../../server/routes/river-and-sea-levels'))
- }
- }
- }
-
- await server.register(require('../../server/plugins/views'))
- await server.register(require('../../server/plugins/session'))
- await server.register(riversPlugin)
- // Add Cache methods to server
- const registerServerMethods = require('../../server/services/server-methods')
- registerServerMethods(server)
-
- await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels?riverId=river-nidd'
@@ -2730,30 +988,10 @@ lab.experiment('Test - /river-and-sea-levels', () => {
Code.expect(response.statusCode).to.equal(302)
Code.expect(response.headers.location).to.equal('/river-and-sea-levels/river/river-nidd')
})
- lab.test('GET /river-and-sea-levels/river/river-nidd', async () => {
- const floodService = require('../../server/services/flood')
-
- const riverStation = () => data.riverNiddStations
-
- sandbox.stub(floodService, 'getRiverById').callsFake(riverStation)
-
- const riversPlugin = {
- plugin: {
- name: 'rivers',
- register: (server, options) => {
- server.route(require('../../server/routes/river-and-sea-levels'))
- }
- }
- }
- await server.register(require('../../server/plugins/views'))
- await server.register(require('../../server/plugins/session'))
- await server.register(riversPlugin)
- // Add Cache methods to server
- const registerServerMethods = require('../../server/services/server-methods')
- registerServerMethods(server)
+ lab.test('GET /river-and-sea-levels/river/river-nidd', async () => {
+ stubs.getRiverById.callsFake(() => data.riverNiddStations)
- await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels/river/river-nidd'
@@ -2768,36 +1006,11 @@ lab.experiment('Test - /river-and-sea-levels', () => {
const riversTab = root.querySelectorAll('ul#filter.defra-navbar__list li.defra-navbar__item--selected')[0].text.trim()
Code.expect(riversTab).to.be.equal('River (6)')
})
- lab.test('GET /river-and-sea-levels - Check for related content links', async () => {
- const floodService = require('../../server/services/flood')
-
- const fakeIsEngland = () => {
- return { is_england: true }
- }
-
- const fakeStationsData = () => []
-
- sandbox.stub(floodService, 'getIsEngland').callsFake(fakeIsEngland)
- sandbox.stub(floodService, 'getStations').callsFake(fakeStationsData)
- const riversPlugin = {
- plugin: {
- name: 'rivers',
- register: (server, options) => {
- server.route(require('../../server/routes/river-and-sea-levels'))
- }
- }
- }
-
- await server.register(require('../../server/plugins/views'))
- await server.register(require('../../server/plugins/session'))
- await server.register(require('../../server/plugins/logging'))
- await server.register(riversPlugin)
- // Add Cache methods to server
- const registerServerMethods = require('../../server/services/server-methods')
- registerServerMethods(server)
+ lab.test('GET /river-and-sea-levels - Check for related content links', async () => {
+ stubs.getStations.callsFake(() => [])
+ stubs.getIsEngland.callsFake(() => ({ is_england: true }))
- await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels'
@@ -2812,14 +1025,3 @@ lab.experiment('Test - /river-and-sea-levels', () => {
})
})
})
-
-function checkTitleAndDescription (root, title, description) {
- const metaDescription = root
- .querySelectorAll('[name="description"]')
-
- const metaTitle = root
- .querySelectorAll('[property="og:title"]')
-
- Code.expect(metaDescription[0]._attrs.content).to.equal(description)
- Code.expect(metaTitle[0]._attrs.content).to.contain(title)
-}