diff --git a/package-lock.json b/package-lock.json
index e3385483a..cd1faabe0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "flood-app",
- "version": "8.5.0",
+ "version": "8.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "flood-app",
- "version": "8.5.0",
+ "version": "8.4.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.13",
+ "node-html-parser": "^6.1.11",
"nodemon": "^3.0.1",
"proxyquire": "^2.1.3"
},
@@ -8791,9 +8791,9 @@
}
},
"node_modules/node-html-parser": {
- "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==",
+ "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==",
"dev": true,
"dependencies": {
"css-select": "^5.1.0",
diff --git a/package.json b/package.json
index 96ee182e3..b65dcce5f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "flood-app",
- "version": "8.5.0",
+ "version": "8.4.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.13",
+ "node-html-parser": "^6.1.11",
"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
deleted file mode 100644
index 3ec86f03b..000000000
--- a/release-docs/CFF-8.5.0.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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 0a109a20f..65ef129d3 100644
--- a/server/models/views/alerts-and-warnings.js
+++ b/server/models/views/alerts-and-warnings.js
@@ -2,39 +2,36 @@ const { bingKeyMaps } = require('../../config')
const config = require('../../config')
class ViewModel {
- constructor ({ q, location, place, floods = [], station, canonical, error }) {
+ constructor ({ location, place, floods, station, error }) {
Object.assign(this, {
- q,
- station,
+ q: location,
map: station ? 'map-station' : 'map',
- placeName: place?.name || '',
- placeBbox: place?.bbox2k || [],
- placeCentre: place?.center || [],
+ station: station || null,
+ placeName: place ? place.name : '',
+ placeBbox: place ? place.bbox2k : [],
+ placeCentre: place ? place.center : [],
timestamp: Date.now(),
- metaCanonical: canonical,
- canonicalUrl: canonical,
- error: !!error,
+ error: error ? true : null,
displayGetWarningsLink: true,
displayLongTermLink: true,
- isEngland: place?.isEngland?.is_england,
- isDummyData: floods?.isDummyData,
+ isEngland: place ? place.isEngland.is_england : null,
+ isDummyData: floods ? floods.isDummyData : false,
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?.length ?? 0
- this.floods = floods?.groups?.map(item => item)
+ this.countFloods = floods ? floods.floods.length : 0
+ this.floods = 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 6579a4437..dc100de3b 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, canonical, q }) {
+function placeViewModel ({ location, place, stations = [], queryGroup }) {
let distStatement, title, description
const isEngland = place ? place.isEngland.is_england : true
@@ -128,10 +128,10 @@ function placeViewModel ({ location, place, stations = [], queryGroup, canonical
deleteUndefinedProperties(stations)
if (location && isEngland) {
- title = `${place.name ?? location} - ${pageTitle}`
+ title = `${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 = place ? `${place.name} - ${pageTitle}` : pageTitle
+ title = location ? `${location} - ${pageTitle}` : pageTitle
description = metaDescription
}
@@ -141,15 +141,13 @@ function placeViewModel ({ location, place, stations = [], queryGroup, canonical
filters,
floodRiskUrl,
distStatement,
- q: q || location,
+ q: location,
clientModel: getClientModel(isEngland ? place.bbox10k : []),
queryGroup: activeFilter,
placeAddress: place.address,
...getDataJourneyClickStrings(),
pageTitle: title,
- metaDescription: description,
- metaCanonical: canonical,
- canonicalUrl: canonical
+ metaDescription: description
}
}
diff --git a/server/routes/alerts-and-warnings.js b/server/routes/alerts-and-warnings.js
index 66557dc37..f371f2b6c 100644
--- a/server/routes/alerts-and-warnings.js
+++ b/server/routes/alerts-and-warnings.js
@@ -3,160 +3,90 @@ 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: `/${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)
+ 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 })
+ }
}
- }
-},
-{
- 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: `/${route}`,
- handler: routeHandler,
+ 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))}`)
+ },
options: {
validate: {
payload: joi.object({
- location: joi.string()
- .allow('')
- .trim()
- .max(QUERY_STRING_LOCATION_MAX_LENGTH)
- .required()
+ location: joi.string().allow('').trim().max(200).required()
}),
- failAction: (request, h) => failActionHandler(request, h, route)
+ failAction: (request, h, _err) => {
+ return h.view('alerts-and-warnings').takeover()
+ }
}
}
}]
diff --git a/server/routes/lib/utils.js b/server/routes/lib/utils.js
index 5dac60f57..0fb99ff6b 100644
--- a/server/routes/lib/utils.js
+++ b/server/routes/lib/utils.js
@@ -1,57 +1,7 @@
-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,
- failActionHandler,
- isLocationEngland,
- isPlaceEngland,
- isValidLocationSlug,
- renderNotFound,
- renderLocationNotFound,
- createQueryParametersString
+ slugify
}
diff --git a/server/routes/river-and-sea-levels.js b/server/routes/river-and-sea-levels.js
index 46af2b90e..6c0dff8d3 100644
--- a/server/routes/river-and-sea-levels.js
+++ b/server/routes/river-and-sea-levels.js
@@ -12,109 +12,14 @@ 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}`,
@@ -229,48 +134,82 @@ 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) => 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)
+ failAction: (request, h) => {
+ request.logger.warn({
+ situation: 'River and Sea levels search error: Invalid or no string input.'
+ })
+
+ return h.redirect()
+ }
}
}
}, {
method: 'POST',
path: `/${route}`,
- handler: locationQueryHandler,
+ handler: async (request, h) => {
+ const { location } = request.payload
+ return h.redirect(`/${route}?q=${encodeURIComponent(location)}`).takeover()
+ },
options: {
validate: {
payload: joi.object({
location: joi.string()
- .allow('')
.trim()
- .max(QUERY_STRING_LOCATION_MAX_LENGTH)
- .required()
+ .regex(new RegExp(`^[${util.ALLOWED_SEARCH_CHARS}]*$`)).required()
}),
- failAction: (request, h) => failActionHandler(request, h, route)
+ failAction: (_request, h, _err) => h.view(route, { model: emptyResultsModel(_request.payload?.location.trim()) }).takeover()
}
}
}]
+
+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 441023941..6f6f7ad55 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', 'religiousstructure', 'roadblock'
+ 'populatedplace', 'postcode1', 'postcode3', 'admindivision2', 'neighborhood'
]
const data = set.resources
.filter(r => allowedConfidences.includes(r.confidence.toLowerCase()))
diff --git a/server/views/layout.html b/server/views/layout.html
index 60dada24d..f9e35eb87 100644
--- a/server/views/layout.html
+++ b/server/views/layout.html
@@ -30,7 +30,7 @@
{% if metaCanonical %}
-
+
{% endif %}
'
- }
+ url: '/river-and-sea-levels',
+ payload: { location: "" }
}
const response = await server.inject(options)
- Code.expect(response.statusCode).to.equal(404)
- Code.expect(response.result.message).to.equal('Not Found')
+ 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()
})
-
lab.experiment('RLOI', () => {
lab.test('GET /river-and-sea-levels?rloi-id=7224 should redirect', 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 }))
+ 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)
// 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'
@@ -940,18 +2640,39 @@ 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 () => {
- 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 }))
+ 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)
// 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'
@@ -965,19 +2686,40 @@ 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 () => {
- 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 }))
+ 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)
// 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'
@@ -988,10 +2730,30 @@ 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 () => {
- stubs.getRiverById.callsFake(() => data.riverNiddStations)
+ 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)
+ await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels/river/river-nidd'
@@ -1006,11 +2768,36 @@ 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 () => {
- stubs.getStations.callsFake(() => [])
- stubs.getIsEngland.callsFake(() => ({ is_england: true }))
+ 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)
+
+ await server.initialize()
const options = {
method: 'GET',
url: '/river-and-sea-levels'
@@ -1025,3 +2812,14 @@ 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)
+}