diff --git a/package-lock.json b/package-lock.json index b17cff5ca..081cedfd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "flood-app", - "version": "6.2.1", + "version": "6.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "flood-app", - "version": "6.2.1", + "version": "6.3.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 49ad558e3..5cfb2a435 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flood-app", - "version": "6.2.1", + "version": "6.3.0", "description": "Flood risk app", "main": "index.js", "repository": "github:defra/flood-app", diff --git a/release-docs/CFF-6.3.0.txt b/release-docs/CFF-6.3.0.txt new file mode 100644 index 000000000..6a07db4ff --- /dev/null +++ b/release-docs/CFF-6.3.0.txt @@ -0,0 +1,25 @@ +# Check for flooding 6.3.0 Tuesday 4th April 2023 + +# Release + +6.3.0 + +https://eaflood.atlassian.net/projects/FSR/versions/16333/tab/release-report-all-issues + +# Tickets + +https://eaflood.atlassian.net/browse/FSR-621 +https://eaflood.atlassian.net/browse/FSR-634 +https://eaflood.atlassian.net/browse/FSR-635 +https://eaflood.atlassian.net/browse/FSR-720 + +# Instructions + +Straight forward application build for release + +1 - Execute LFW_{STAGE}_02_UPDATE_DATABASE +2 - Execute LFW_{STAGE}_03_UPDATE_GEOSERVER_PIPELINE +3 - Execute LFW_{STAGE}_99_LOAD_RIVERS +4 - Execute LFW_{STAGE}_04_UPDATE_FLOOD_APP_AND_SERVICE_PIPELINE + +Execute smoke tests and forward results diff --git a/server/models/views/rainfall.js b/server/models/views/rainfall.js index 904fe9a4c..60b492837 100644 --- a/server/models/views/rainfall.js +++ b/server/models/views/rainfall.js @@ -32,7 +32,7 @@ class ViewModel { const now = moment().tz(tz).format() const fiveDaysAgo = moment().subtract(5, 'days').format() const latestDateTime = this.telemetry[0].value_timestamp - this.latestDayFormatted = moment(latestDateTime).tz(tz).format('Do MMMM') + this.latestDayFormatted = moment(latestDateTime).tz(tz).format('D MMMM') this.latestTimeFormatted = moment(latestDateTime).tz(tz).format('h:mma') this.outOfDate = lastDataRefresh(this.telemetry[0].value_timestamp) const dataStartDateTime = fiveDaysAgo diff --git a/server/models/views/river-and-sea-levels.js b/server/models/views/river-and-sea-levels.js index 702052aa1..547900cd9 100644 --- a/server/models/views/river-and-sea-levels.js +++ b/server/models/views/river-and-sea-levels.js @@ -185,8 +185,11 @@ function getFormattedTime (station) { } else if (station.value_timestamp) { const formattedTime = moment(station.value_timestamp).tz('Europe/London').format('h:mma') const formattedDate = moment(station.value_timestamp).tz('Europe/London').format('D MMMM') - - return `Updated ${formattedTime}, ${formattedDate} ` + if (station.station_type === 'R') { + return `Totals up to ${formattedTime}, ${formattedDate} ` + } else { + return `Latest at ${formattedTime}, ${formattedDate} ` + } } return null } @@ -232,12 +235,19 @@ function deleteUndefinedProperties (stations) { } function setStationProperties (station) { + const trendSvgPaths = { + falling: 'M9.844 8.419l2.116-2.116 1.697 7.354-7.354-1.697 2.128-2.128-6.789-6.788L3.056 1.63l6.788 6.789z', + rising: 'M8.419 6.156L6.303 4.04l7.354-1.697-1.697 7.354-2.128-2.128-6.788 6.789-1.414-1.414 6.789-6.788z', + steady: 'M9.6,6.992l0,-2.992l6.4,4l-6.4,4l0,-3.009l-9.6,0l0,-1.999l9.6,0Z' + } station.external_name = formatName(station.external_name) station.displayData = getDisplayData(station) station.latestDatetime = station.status === 'Active' ? getFormattedTime(station) : null station.formattedValue = station.status === 'Active' ? formatValue(station, station.value) : null station.state = getStationState(station) station.group_type = getStationGroup(station) + station.trend = station.displayData ? station.trend : null + station.trendSvgPath = trendSvgPaths[station.trend] } function getClientModel (placeBox = []) { diff --git a/server/models/views/station.js b/server/models/views/station.js index 50edd003f..4248221b5 100644 --- a/server/models/views/station.js +++ b/server/models/views/station.js @@ -4,6 +4,7 @@ const config = require('../../config') const Station = require('./station-data') const Forecast = require('./station-forecast') const util = require('../../util') +const tz = 'Europe/London' class ViewModel { constructor (options) { @@ -15,6 +16,7 @@ class ViewModel { this.twitterEvent = 'Station:Share Page:Station - Share to Twitter' this.facebookEvent = 'Station:Share Page:Station - Share to Facebook' this.emailEvent = 'Station:Share Page:Station - Share to email' + this.station.trend = river.trend Object.assign(this, { feedback: false, @@ -28,7 +30,8 @@ class ViewModel { twitterEvent: 'Station:Share Page:Station - Share to Twitter', facebookEvent: 'Station:Share Page:Station - Share to Facebook', emailEvent: 'Station:Share Page:Station - Share to email', - floodRiskUrl: config.floodRiskUrl + floodRiskUrl: config.floodRiskUrl, + trend: river.trend }) // Group warnings/alerts by severity level @@ -137,14 +140,14 @@ class ViewModel { if (diff.asDays() < numberOfProvisionalDays) { this.station.porMaxValueIsProvisional = true } - this.station.formattedPorMaxDate = moment.tz(this.station.porMaxDate, 'Europe/London').format('DD/MM/YY') - this.station.thresholdPorMaxDate = moment.tz(this.station.porMaxDate, 'Europe/London').format('D MMMM YYYY') + this.station.formattedPorMaxDate = moment.tz(this.station.porMaxDate, tz).format('DD/MM/YY') + this.station.thresholdPorMaxDate = moment.tz(this.station.porMaxDate, tz).format('D MMMM YYYY') } } // formatted Status Date and time - this.station.formattedStatusDate = moment.tz(this.station.statusDate, 'Europe/London').format('dddd D MMMM YYYY') - this.station.formattedStatusTime = moment.tz(this.station.statusDate, 'Europe/London').format('h:ma') + this.station.formattedStatusDate = moment.tz(this.station.statusDate, tz).format('dddd D MMMM YYYY') + this.station.formattedStatusTime = moment.tz(this.station.statusDate, tz).format('h:ma') // Gets the latest value object if (this.telemetry.length) { @@ -158,7 +161,9 @@ class ViewModel { if (this.recentValue) { // Get most recent value time - this.recentValue.formattedTime = moment.tz(this.recentValue.ts, 'Europe/London').format('h:mma') + this.recentValue.formattedTime = moment.tz(this.recentValue.ts, tz).format('h:mma') + this.recentValue.latestDayFormatted = moment.tz(this.recentValue.ts).format('D MMMM') + const today = moment().startOf('day') const yesterday = moment().subtract(1, 'days').startOf('day') @@ -169,10 +174,10 @@ class ViewModel { // check if recent value is over one hour old this.dataOverHourOld = new Date(this.recentValue.ts) < oneHourAgo - this.recentValue.dateWhen = 'on ' + moment.tz(this.recentValue.ts, 'Europe/London').format('D/MM/YY') - if (moment.tz(this.recentValue.ts, 'Europe/London').isSame(today, 'd')) { + this.recentValue.dateWhen = 'on ' + moment.tz(this.recentValue.ts, tz).format('D/MM/YY') + if (moment.tz(this.recentValue.ts, tz).isSame(today, 'd')) { this.recentValue.dateWhen = 'today' - } else if (moment.tz(this.recentValue.ts, 'Europe/London').isSame(yesterday, 'd')) { + } else if (moment.tz(this.recentValue.ts, tz).isSame(yesterday, 'd')) { this.recentValue.dateWhen = 'yesterday' } @@ -335,6 +340,40 @@ class ViewModel { }) } + if (this.station.type === 'c' && river.river_id !== 'Sea Levels') { + this.station.isTidal = true + } + + // Toggletips + if ((this.station.type === 's') || (this.station.type === 'm') || (this.station.type === 'g') || (this.station.isTidal)) { + this.infoHeight = (() => { + if (Number(station.stage_datum) === 0) { + return 'This station measures height from sea level.' + } else if (this.recentValueBelowZero) { + return 'This station measures height from a fixed point on or close to the riverbed.' + + ' A reading of 0 metres can be normal for some stations because of natural changes to the riverbed.' + } else { + return 'This station measures height from a fixed point on or close to the riverbed.' + } + })() + this.infoState = (() => { + let state + switch (this.station.state) { + case 'High': + state = 'above' + break + case 'Low': + state = 'below' + break + default: + state = 'within' + } + return `There are 3 states: low, normal and high. The latest level is ${state} the normal range. ` + + 'We calculate the normal range using an average of past measurements and other local factors.' + })() + } + this.infoTrend = 'The last 2 readings indicate the trend.' + // Group and sort thresholds thresholds = thresholds.reduce( (result, item) => ({ diff --git a/server/routes/station.js b/server/routes/station.js index 1a3827155..166a88a45 100644 --- a/server/routes/station.js +++ b/server/routes/station.js @@ -43,7 +43,7 @@ module.exports = { request.server.methods.flood.getStationForecastThresholds(id), request.server.methods.flood.getImpactData(station.rloi_id), request.server.methods.flood.getWarningsAlertsWithinStationBuffer(station.rloi_id), - request.server.methods.flood.getRiverStationByStationId(id) + request.server.methods.flood.getRiverStationByStationId(id, direction) ]) if (station.status === 'Closed') { diff --git a/server/services/flood.js b/server/services/flood.js index c42ee1705..e86123b3b 100644 --- a/server/services/flood.js +++ b/server/services/flood.js @@ -55,8 +55,8 @@ module.exports = { return util.getJson(`${serviceUrl}/river/${id}`) }, - getRiverStationByStationId (id) { - return util.getJson(`${serviceUrl}/river-station-by-station-id/${id}`) + getRiverStationByStationId (id, direction) { + return util.getJson(`${serviceUrl}/river-station-by-station-id/${id}/${direction}`) }, getRainfallStationTelemetry (id) { diff --git a/server/src/js/components/map/live.js b/server/src/js/components/map/live.js index 0623ac820..e213eb1e5 100644 --- a/server/src/js/components/map/live.js +++ b/server/src/js/components/map/live.js @@ -358,7 +358,7 @@ function LiveMap (mapId, options) { const formattedExpiredTime = moment(date).tz('Europe/London').format('h:mma') const formattedExpiredDate = moment(date).tz('Europe/London').format('D MMMM') - return `Recent rainfall up to ${formattedExpiredTime}, ${formattedExpiredDate}` + return `Totals up to ${formattedExpiredTime} on ${formattedExpiredDate}` } // Time format function @@ -370,31 +370,10 @@ function LiveMap (mapId, options) { } // Day format function - const formatDay = (date) => { + const formatDayMonth = (date) => { const day = date.getDate() - const nth = (day) => { - if (day > 3 && day < 21) return 'th' - switch (day % 10) { case 1: return 'st'; case 2: return 'nd'; case 3: return 'rd'; default: return 'th' } - } - const shortDay = date.toLocaleString('en-GB', { weekday: 'short' }) - const today = new Date() - const yesterday = new Date() - const tomorrow = new Date() - today.setHours(0, 0, 0, 0) - yesterday.setDate(yesterday.getDate() - 1) - yesterday.setHours(0, 0, 0, 0) - tomorrow.setDate(tomorrow.getDate() + 1) - tomorrow.setHours(0, 0, 0, 0) - date.setHours(0, 0, 0, 0) - if (date.getTime() === today.getTime()) { - return 'today' - } else if (date.getTime() === yesterday.getTime()) { - return 'yesterday' - } else if (date.getTime() === tomorrow.getTime()) { - return 'tomorrow' - } else { - return ' on ' + shortDay + ' ' + date.getDate() + nth(day) - } + const month = date.toLocaleString('en-GB', { month: 'long' }) + return `${day} ${month}` } const capitalise = (str) => { @@ -407,8 +386,9 @@ function LiveMap (mapId, options) { model.id = feature.getId().substring(feature.getId().indexOf('.') + 1) // Format dates for river levels if (feature.getId().startsWith('stations')) { - model.date = formatTime(new Date(model.value_date)) + ' ' + formatDay(new Date(model.value_date)) + model.date = `${formatTime(new Date(model.value_date))} on ${formatDayMonth(new Date(model.value_date))}` model.state = feature.get('state') + model.trend = feature.get('trend') } if (feature.getId().startsWith('rainfall')) { model.id = feature.getId().toString().split('.')[1] diff --git a/server/src/js/components/toggletip.js b/server/src/js/components/toggletip.js index 27c1a36c6..d1e60c076 100644 --- a/server/src/js/components/toggletip.js +++ b/server/src/js/components/toggletip.js @@ -5,44 +5,49 @@ const { forEach } = window.flood.utils const toggletips = () => { + // Reference to timeout + let timeout + // Add tooltip - const openToggletip = (button) => { - // Update reference - currentButton = button + const openToggletip = (toggletip) => { // Outer margin const viewportMargin = 15 // Determin position of overlay - const info = button.nextElementSibling - const text = info.querySelector('span:first-child') + const info = toggletip.querySelector('.defra-toggletip__info') + const text = info.querySelector('.defra-toggletip__text') const arrow = info.querySelector('.defra-toggletip__arrow') text.innerHTML = '' - // Timeout recommend to ensure aria-live region is re-read - window.setTimeout(() => { - text.innerHTML = button.parentNode.getAttribute('data-toggletip-content') - button.parentNode.classList.add('defra-toggletip--open') - const buttonLeft = button.getBoundingClientRect().left - const buttonWidth = button.getBoundingClientRect().width + // Timeout recommended to ensure aria-live region is re-read + timeout = window.setTimeout(() => { + // Update reference + closeToggletips() + currentToggletip = toggletip + text.innerHTML = `${toggletip.getAttribute('data-toggletip-content')}` + toggletip.classList.add('defra-toggletip--open') + const target = toggletip.querySelector('.defra-toggletip-target') || toggletip + const targetWidth = target.getBoundingClientRect().width + const targetLeft = target.getBoundingClientRect().left const viewportWidth = window.innerWidth let infoWidth = info.getBoundingClientRect().width + // Limit info width when zoomed infoWidth = infoWidth > (viewportWidth - (viewportMargin * 2)) ? viewportWidth - (viewportMargin * 2) : infoWidth - // Centre tip - let infoOffsetX = ((infoWidth - buttonWidth) / 2) - (((infoWidth - buttonWidth) / 2) * 2) + let infoOffsetX = (targetWidth - infoWidth) / 2 // Correct offset if near sides - if ((buttonLeft + infoOffsetX) < viewportMargin) { + if ((targetLeft + infoOffsetX) < viewportMargin) { // Left side - infoOffsetX = viewportMargin - buttonLeft - } else if ((buttonLeft + infoWidth + infoOffsetX) > (viewportWidth - viewportMargin)) { + infoOffsetX = viewportMargin - targetLeft + } else if ((targetLeft + infoOffsetX + infoWidth) > (viewportWidth - viewportMargin)) { // Right side - infoOffsetX = (viewportWidth - viewportMargin - buttonLeft) - infoWidth + infoOffsetX = (viewportWidth - viewportMargin - infoWidth) - targetLeft } - arrow.style.left = `${Math.abs(infoOffsetX) + Math.round((buttonWidth / 2))}px` + arrow.style.left = `${(0 - infoOffsetX) + (targetWidth / 2)}px` info.style.marginLeft = `${infoOffsetX}px` // Overide width so it doesn't truncate at zoom levels info.style.width = `${infoWidth}px` // Switch position if near top if (info.getBoundingClientRect().top < viewportMargin) { - button.parentNode.classList.add('defra-toggletip--bottom') + toggletip.classList.add('defra-toggletip--bottom') } }, 100) } @@ -50,10 +55,11 @@ const toggletips = () => { // Remove tooltip const closeToggletips = () => { // Update reference - currentButton = null + clearTimeout(timeout) + currentToggletip = null const toggletips = document.querySelectorAll('.defra-toggletip--open') if (toggletips.length) { - forEach(toggletips, (toggletip) => { + forEach(toggletips, toggletip => { toggletip.classList.remove('defra-toggletip--open') toggletip.classList.remove('defra-toggletip--bottom') toggletip.classList.remove('defra-toggletip--keyboard-focus') @@ -69,27 +75,46 @@ const toggletips = () => { } // Reference to current button - let currentButton + let currentToggletip // Create toggletips - const toggletips = document.querySelectorAll('.defra-toggletip') + const toggletips = document.querySelectorAll('[data-toggletip]') forEach(toggletips, (toggletip) => { - const button = document.createElement('button') - button.className = 'defra-toggletip__button' - button.setAttribute('aria-label', toggletip.getAttribute('data-label')) - button.innerHTML = 'i' const info = document.createElement('span') info.className = 'defra-toggletip__info' info.setAttribute('role', 'status') - info.innerHTML = '' - toggletip.appendChild(button) - toggletip.appendChild(info) + info.innerHTML = '' + toggletip.classList.add('defra-toggletip') + const container = document.createElement('span') + container.className = 'defra-toggletip__container' + container.setAttribute('data-toggletip-container', '') + const button = document.createElement('button') + button.className = 'defra-toggletip__button defra-toggletip-target' + button.setAttribute('aria-label', toggletip.getAttribute('data-toggletip-label') || 'More information') + button.innerHTML = ` + + + + i + ` + container.appendChild(button) + container.appendChild(info) + toggletip.appendChild(container) }) // Add on click document.addEventListener('click', (e) => { - const isButton = e.target.classList && e.target.classList.contains('defra-toggletip__button') - isButton ? openToggletip(e.target) : closeToggletips() + const isTarget = e.target.classList.contains('defra-toggletip-target') + const isInfo = !!e.target.closest('.defra-toggletip__info') + if (isTarget) { + const toggletip = e.target.closest('.defra-toggletip') + openToggletip(toggletip) + } else if (!isInfo) { + closeToggletips() + } }) // Remove on escape @@ -101,40 +126,46 @@ const toggletips = () => { // Add on mouse enter document.addEventListener('mouseenter', (e) => { - if (e.target.classList && e.target.classList.contains('defra-toggletip__button')) { - closeToggletips() - openToggletip(e.target) + if (e.target === document) return + const isTarget = !!e.target.closest('.defra-toggletip-target') + if (isTarget && !currentToggletip) { + const toggletip = e.target.closest('.defra-toggletip') + openToggletip(toggletip) } }, true) // Remove on mouse leave document.addEventListener('mouseleave', (e) => { - if (e.target.classList && e.target.classList.contains('defra-toggletip__button')) { + if (e.target === document) return + const isTarget = e.target.hasAttribute('data-toggletip-container') + if (isTarget) { closeToggletips() } }, true) // Add on focus - // document.addEventListener('focusin', (e) => { - // if (e.target.classList && e.target.classList.contains('defra-toggletip__button')) { - // closeToggletips() - // openToggletip(e.target) - // } - // }) + document.addEventListener('focusin', (e) => { + const toggletip = e.target.closest('.defra-toggletip') + if (toggletip) { + closeToggletips() + openToggletip(toggletip) + } + }) // Remove on blur document.addEventListener('focusout', (e) => { - if (e.target.classList && e.target.classList.contains('defra-toggletip__button')) { + const toggletip = e.target.closest('.defra-toggletip') + if (toggletip) { closeToggletips() } }) // Page zoom - window.addEventListener('resize', (e) => { - if (currentButton) { - openToggletip(currentButton) - } - }) + // window.addEventListener('resize', (e) => { + // if (currentToggletip) { + // openToggletip(currentToggletip) + // } + // }) } window.flood.createToggletips = () => { diff --git a/server/src/js/pages/rainfall.js b/server/src/js/pages/rainfall.js index 51ab925be..5a721536e 100644 --- a/server/src/js/pages/rainfall.js +++ b/server/src/js/pages/rainfall.js @@ -30,7 +30,7 @@ if (document.getElementById('bar-chart')) { window.flood.charts.createBarChart('bar-chart', window.flood.model.stationId, window.flood.model.telemetry) } -// Add toggletips -if (document.querySelectorAll('.defra-toggletip')) { +// Toggletips +if (document.querySelectorAll('[data-toggletip]')) { window.flood.createToggletips() } diff --git a/server/src/js/pages/station.js b/server/src/js/pages/station.js index 31501dbf1..64a2f574f 100644 --- a/server/src/js/pages/station.js +++ b/server/src/js/pages/station.js @@ -8,6 +8,7 @@ import '../components/map/layers' import '../components/map/container' import '../components/map/live' import '../components/toggle-list-display' +import '../components/toggletip' // Create LiveMap window.flood.maps.createLiveMap('map', { @@ -95,3 +96,8 @@ if (toggleListDisplay) { btnText: 'historical events' }) } + +// Toggletips +if (document.querySelectorAll('[data-toggletip]')) { + window.flood.createToggletips() +} diff --git a/server/src/sass/components/_chart-controls.scss b/server/src/sass/components/_chart-controls.scss index 262502438..215553514 100644 --- a/server/src/sass/components/_chart-controls.scss +++ b/server/src/sass/components/_chart-controls.scss @@ -47,7 +47,6 @@ .defra-chart-pagination { display: block; padding-bottom: 15px; - border-bottom: 1px solid $govuk-border-colour; &__button { border: 0px; background-color: white; diff --git a/server/src/sass/components/_flood-levels-table.scss b/server/src/sass/components/_flood-levels-table.scss index f280bd558..0cdbdaf30 100644 --- a/server/src/sass/components/_flood-levels-table.scss +++ b/server/src/sass/components/_flood-levels-table.scss @@ -1,112 +1,188 @@ .defra-flood-levels-table { - @extend .govuk-table; - position: relative; - margin-top: -1px; - margin-bottom: 0px; + @extend .govuk-table; + position: relative; + margin-top: -1px; + margin-bottom: 0px; + @include mq ($until: tablet) { + display: block; + } + &__caption { + // @extend .govuk-table__caption; + // @extend .govuk-table__caption--m; + // margin-top: 15px; + @extend .govuk-visually-hidden; + // @include mq ($until: tablet) { + // display: block; + // } + } + &__head { @include mq ($until: tablet) { display: block; + } + } + &__head tr { + @include mq ($until: tablet) { + display: flex; + flex-wrap: wrap; } - &__body { - @include mq ($until: tablet) { - display: block; - } + } + &__head &__cell { + text-align: left; + @include govuk-font($size: 16, $weight: bold); + @include mq ($until: tablet) { + color: $govuk-secondary-text-colour; } - &__row { - border-top: 1px solid govuk-tint($govuk-border-colour, 50); + &--location { @include mq ($until: tablet) { - display: block; - overflow: auto; + @include defra-visually-hidden(); } } - &__row--hidden { - display:none; + } + &__body { + @include mq ($until: tablet) { + display: block; } - &__cell { - @extend .govuk-table__cell; - border-bottom: 0px; - vertical-align: middle; - text-align: left; - padding-left: 0px; - padding-right: 0px; - @include mq ($until: tablet) { - border: 0px; - float: left; - } - a:not(:hover) { - text-decoration: none; - } + } + &__row { + border-top: 1px solid govuk-tint($govuk-border-colour, 70); + border-bottom: 1px solid govuk-tint($govuk-border-colour, 70); + @include mq ($until: tablet) { + position: relative; + display: flex; + flex-wrap: wrap; + margin-bottom: -1px; } - &__cell--location { - @include govuk-font($size: 19, $weight: bold); - width: 50%; - padding-right:20px; - @include mq ($until: tablet) { - padding-right: 0px; - display: block; - width: 100%; - } + } + &__cell { + @extend .govuk-table__cell; + border-bottom: 0px; + vertical-align: middle; + text-align: left; + padding-left: 0px; + padding-right: 0px; + @include mq ($until: tablet) { + display: inline-block; } - &__cell--location-rainfall { - @include govuk-font($size: 19, $weight: bold); - width: 40%; - padding-right:20px; - @include mq ($until: tablet) { - padding-right: 0px; - display: block; - width: 100%; - } + a { + display: inline-block; } - &__cell--height { - width: 20%; - @include mq ($until: tablet) { - padding-top:0px; - width: 70%; - } + a:not(:hover) { + text-decoration: none; } - &__cell--state { - width: 10%; - @include mq ($until: tablet) { - padding-top:0px; - width: 30%; - } + } + &__cell--location { + @include govuk-font($size: 19, $weight: bold); + width: 50%; + padding-right:20px; + @include mq ($until: tablet) { + padding-top:10px; + padding-right: 0px; + width: 100%; } - &__cell--rainfall { - width: 20%; - @include mq ($until: tablet) { - padding-top: 0px; - width: 33.33%; - min-width: 4em; - } + } + &__cell--location-rainfall { + @include govuk-font($size: 19, $weight: bold); + width: 40%; + padding-right:20px; + @include mq ($until: tablet) { + padding-top:10px; + padding-right: 0px; + width: 100%; } - &-meta { - display: block; - @include govuk-font($size: 16); - color: $govuk-secondary-text-colour; + } + &__cell--height { + width: 17%; + @include mq ($until: tablet) { + width: auto; + flex: 1 1 1em; } - &-subtitle { - display: block; - @include govuk-font($size: 16); + } + &__cell--trend { + width: 22%; + @include mq ($until: tablet) { + width: auto; + flex: 1 1 3.5em; } - &-na { - @include govuk-font($size: 16); + } + &__cell--state { + width: 10%; + @include mq ($until: tablet) { + width: auto; + flex: 1 1 0.5em; } - &-numeric { - @include govuk-font($size: 19, $tabular: true); - display: inline-block; - padding-top: 4px; - padding-bottom: 4px; + } + &__cell--rainfall { + width: 20%; + @include mq ($until: tablet) { + width: auto; + flex: 1 1 auto; } - &-state { - position: relative; - @include govuk-font($size: 19, $weight: normal); - text-transform: uppercase; - // color: $govuk-secondary-text-colour; - background-color: govuk-colour('light-grey'); - display: inline-block; - padding: 4px 8px; - &--blue { - color: govuk-colour('dark-blue'); - background-color: govuk-tint(govuk-colour('blue'), 80); + } + &-subtitle { + display: block; + @include govuk-font($size: 16); + } + &-meta { + display: block; + @include govuk-font($size: 16); + color: $govuk-secondary-text-colour; + } + &-na { + @include govuk-font($size: 16); + } + &-numeric { + @include govuk-font($size: 19, $tabular: true); + display: inline-block; + padding-top: 4px; + padding-bottom: 4px; + } + &-state { + position: relative; + @include govuk-font($size: 19, $weight: normal); + text-transform: uppercase; + // color: $govuk-secondary-text-colour; + background-color: govuk-colour('light-grey'); + display: inline-block; + padding: 4px 8px; + &--blue { + color: govuk-colour('dark-blue'); + background-color: govuk-tint(govuk-colour('blue'), 80); + } + } + &-trend { + padding: 4px; + display: inline-block; + // color: $govuk-secondary-text-colour; + position: relative; + text-transform: uppercase; + @include govuk-font($size: 19, $weight: normal); + padding-left: 30px; + @include mq ($from: tablet) { + padding-left: 36px; + } + &__icon { + position: absolute; + border-radius: 100%; + border: 1px solid govuk-colour('mid-grey'); + width: 24px; + height: 24px; + left: 0px; + top: 1px; + @include mq ($from: tablet) { + width: 28px; + height: 28px; + top: 2px; + } + } + svg { + position: absolute; + left: 4px; + top: 4px; + color: govuk-colour('black'); + @include mq ($from: tablet) { + left:6px; + top: 6px; } } } +} diff --git a/server/src/sass/components/_flood-statistics.scss b/server/src/sass/components/_flood-statistics.scss index 51be23a68..9923c96c5 100644 --- a/server/src/sass/components/_flood-statistics.scss +++ b/server/src/sass/components/_flood-statistics.scss @@ -1,50 +1,31 @@ .defra-flood-statistics { - border-top: 1px solid $govuk-border-colour; - border-bottom: 1px solid $govuk-border-colour; &__list { margin:0; - @include mq ($from: tablet) { - margin-left:-15px; - margin-right:-15px; - } } &__list:after { content:''; display:block; clear:both; } - &__column-one-quarter { - width:50%; - box-sizing: border-box; - padding-right: 10px; - float:left; - @include mq ($from: tablet) { - padding: 0px 15px; - width:33.33%; - } - } - &__column-one-third { + &__item { width:33.33%; box-sizing: border-box; padding-right: 10px; float:left; - @include mq ($from: tablet) { - padding: 0px 15px; + min-width: 6em; + @include mq ($from: desktop) { + width: 25%; } } &__key { - // @include govuk-font($size: 19, $weight: bold); @include govuk-font($size: 19); - padding-top: 20px; - margin-bottom: 5px; + color: $govuk-secondary-text-colour; } &__value { - @include govuk-font($size: 36); - // color: govuk-colour('blue'); + @include govuk-font($size: 27); margin:0; display: block; box-sizing: border-box; - padding-bottom: 20px; } &__value::first-letter { margin-left: -0.075em; @@ -53,10 +34,15 @@ border-bottom: 0px; margin-bottom: 0px; } - &__value-detail { - @include govuk-font($size: 16); - color: $govuk-text-colour; - margin-top: 5px; - display: block; + &--border { + border-top: 1px solid $govuk-border-colour; + border-bottom: 1px solid $govuk-border-colour; + padding-bottom: 15px; + @include mq ($from: tablet) { + padding-bottom: 20px; + } + } + &--border &__key { + padding-top: 15px; } } diff --git a/server/src/sass/components/_navbar.scss b/server/src/sass/components/_navbar.scss index b9fff7ae0..5aee7de6b 100644 --- a/server/src/sass/components/_navbar.scss +++ b/server/src/sass/components/_navbar.scss @@ -1,148 +1,205 @@ .defra-navbar { - position: relative; - z-index: 1; + position: relative; + z-index: 1; + @include govuk-font($size: 19); + margin: 7px -15px 10px -15px; + @include mq ($from: tablet) { @include govuk-font($size: 16); - margin-right: -15px; - margin-left: -15px; - display: flex; - flex-wrap: nowrap; - overflow-x: auto; - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; - -webkit-overflow-scrolling: touch; - @include mq ($from: tablet) { - margin-right: 0px; - margin-left: 0px; - } - &:before { - @include mq ($until: tablet) { - position: absolute; - content: ''; - height: 100%; - width: 15px; - left: 0px; - } - } - &::-webkit-scrollbar { - display: none; - } - &__inner { - flex: 0 0 auto; - padding-left: 15px; - padding-right: 15px; - @include mq ($from: tablet) { - padding-left: 0px; - padding-right: 0px; - } - } - &__group { - float: left; - } - &__list { - list-style: none; - margin: 0px 0px -1px; - padding: 0px; - } - &__list:after { + margin-bottom: 15px; + } + display: flex; + flex-wrap: nowrap; + overflow-x: auto; + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; + -webkit-overflow-scrolling: touch; + &:before { + @include mq ($until: tablet) { + position: absolute; content: ''; - clear: both; - width: 0px; - height: 0px; - } - &__item { - color: $govuk-secondary-text-colour; - float: left; - margin-right: 15px; + height: 100%; + width: 15px; + left: 0px; } - &__item:last-child { - margin-right: 0px; + } + &::-webkit-scrollbar { + display: none; + } + &__inner { + flex: 0 0 auto; + padding: 3px 15px 4px 15px; + // @include mq ($from: tablet) { + // padding-left: 0px; + // padding-right: 0px; + // } + } + &__group { + float: left; + } + &__list { + list-style: none; + margin: 0px 0px -1px; + padding: 0px; + } + &__list:after { + content: ''; + clear: both; + width: 0px; + height: 0px; + } + &__item { + float: left; + margin-right: 10px; + } + &__item:last-child { + margin-right: 0px; + } + a { + display: inline-block; + position: relative; + padding: 5px 0px 5px 0px; + border: 0px; + color: govuk-colour('black'); + } + a:visited { + color: govuk-colour('black'); + } + a:focus { + background-color: $govuk-focus-colour; + color: govuk-colour('black'); + border: 0px; + box-shadow: 0 4px 0 govuk-colour('black'); + outline: 3px solid transparent; + } + // Overides + .defra-link-icon-s { + @include govuk-font($size: 19); + @include mq ($from: tablet) { + @include govuk-font($size: 16); } - a { - display: inline-block; - position: relative; - outline: 3px solid transparent; - margin-bottom: 0px; - padding: 5px 0px 5px 0px; + float: left; + margin-right: 10px; + &:not([keyboard-focus]):focus { + background-color: white; + // border-color: govuk-colour('mid-grey'); border: 0px; color: govuk-colour('black'); + box-shadow: none; + text-decoration: underline; } - a:visited { + &:hover { color: govuk-colour('black'); - } - &__item--selected a { background-color: transparent; - border-bottom: 4px solid currentColor; + svg { + color: govuk-colour('black'); + } } - a:focus { - background-color: $govuk-focus-colour; + &:active { color: govuk-colour('black'); - border: 0px; - box-shadow: 0 4px 0 govuk-colour('black'); - margin-bottom: 4px; } - // Overides - .defra-button-secondary, - .defra-link-icon-s { + } + // Modifiers + &--search-categories { + margin: 17px -15px 0px -15px; + // @include mq ($from: tablet) { + // margin-left: 0px; + // margin-right: 0px; + // } + border-bottom: 1px solid $govuk-border-colour; + @include mq ($from: tablet) { + border-bottom: 0px; + } + &:after { + @include mq ($from: tablet) { + content: ''; + position: absolute; + left:0px; + right:0px; + bottom:0px; + border-bottom: 1px solid $govuk-border-colour; + z-index: -1; + left: 15px; + right: 15px; + } + } + .defra-navbar__inner { + padding-bottom: 0px; + @include mq ($from: tablet) { + padding-bottom: 1px; + } + } + .defra-navbar__item { + margin: 0px; + } + .defra-button-secondary { + @include govuk-font($size: 19); + @include mq ($from: tablet) { + @include govuk-font($size: 16); + } float: left; border: 0px; - color: govuk-colour('black'); - margin: 0px 15px 4px 0px; - padding: 5px 0px 5px 21px; - &:focus { - color: govuk-colour('black'); - box-shadow: 0 4px 0 govuk-colour('black'); + color: $govuk-link-colour; + margin: 0px 7.5px 4px 0px; + padding-top: 7.5px; + padding-bottom: 7.5px; + text-decoration: none; + &:visited { + color: $govuk-link-colour; } - &:hover { - color: govuk-colour('black'); + &:hover, &:active { background-color: transparent; - svg { - color: govuk-colour('black'); - } + color: $govuk-link-hover-colour; } - &:active { + &:focus { color: govuk-colour('black'); + box-shadow: 0 4px 0 govuk-colour('black'); + } + &:not([keyboard-focus]):focus { + background-color: white; + color: $govuk-link-colour; + box-shadow: none; + border: 0px; } - } - .defra-button-secondary { &:after { content: 'Map'; } svg { + position: relative; + display: inline-block; color: govuk-colour('black'); - top:50%; - margin-top: -10px; - left:1px; + vertical-align: top; + left: 0px; + margin: 0px 7px -3px 1px; + top: -1px; } span { @include defra-visually-hidden(); } } - // Modifiers - &--border { - border-bottom: 1px solid $govuk-border-colour; + .defra-navbar__item a { + color: $govuk-link-colour; + text-decoration: none; + padding: 7.5px; } - &--search-categories { - padding-bottom: 12px; - margin-top: 12px; - @include mq ($from: tablet) { - margin-top: 30px; - } - a, .defra-link-icon-s, .defra-button-secondary { - color: $govuk-link-colour; - text-decoration: none; - } - a:visited, .defra-link-icon-s:visited, .defra-button-secondary:visited { - color: $govuk-link-colour; - } - a:hover, .defra-link-icon-s:hover, .defra-button-secondary:hover { + .defra-navbar__item a:visited { + color: $govuk-link-colour; + } + .defra-navbar__item a:hover { + color: $govuk-link-hover-colour; + svg { color: $govuk-link-hover-colour; - svg { - color: $govuk-link-hover-colour; - } } - a:focus, .defra-link-icon-s:focus, .defra-button-secondary:focus { + } + .defra-navbar__item a:focus { + color: govuk-colour('black'); + svg { color: govuk-colour('black'); } } + .defra-navbar__item--selected a:not(:focus) { + background-color: transparent; + border-bottom: 4px solid currentColor; + color: $govuk-link-colour; + } } - \ No newline at end of file +} diff --git a/server/src/sass/components/_toggletip.scss b/server/src/sass/components/_toggletip.scss index ee6f94b3c..739974e92 100644 --- a/server/src/sass/components/_toggletip.scss +++ b/server/src/sass/components/_toggletip.scss @@ -1,94 +1,144 @@ .defra-toggletip { - display: inline-block; - position: relative; - width: 30px; - height: 30px; - z-index: 1; - vertical-align: top; - margin-top: -5px; - @include mq ($from: tablet) { - margin-top: -2px; - } - @include govuk-font($size: 16); - &--open { - z-index: 99; - } - &__button { - position: absolute; - width: 30px; - height: 30px; - background-color: white; - outline: 3px solid transparent; - border: 0px; - text-align: center; - color: $govuk-text-colour; - cursor: pointer; - span { - pointer-events: none; - position: absolute; - top: 5px; - left: 5px; - width: 18px; - height: 18px; - line-height: 18px; - font-weight: 900; - border-radius: 100%; - border: 1px solid govuk-colour('black'); - font-size: 12px; - } - &:hover, &:focus { - color: govuk-colour('black'); - } - &:hover span { - box-shadow: 0 0 0 5px govuk-colour('mid-grey'); - } - &:focus span { - box-shadow: 0 0 0 1px govuk-colour('black'), 0 0 0 5px $govuk-focus-colour; - } - } - &__info { - position:absolute; - width:0px; - overflow: hidden; - box-sizing: border-box; - visibility: hidden; - top: auto; - bottom: 100%; - left: 0px; - margin-bottom: 10px; - padding: 7.5px 10px; - text-align: left; - background: govuk-colour('black'); - color: white; - } - &__arrow { - position: absolute; - z-index: 1; - width: 8px; - height: 8px; - left: 50%; - bottom: auto; - top: 100%; - margin: -4px 0px 0px -4px; - background: govuk-colour('black'); - -webkit-transform: rotate(135deg); - -moz-transform: rotate(135deg); - -o-transform: rotate(135deg); - transform: rotate(135deg); - } - &--bottom &__info { - bottom: auto; - top: 100%; - margin-top: 10px; - } - &--bottom &__arrow { - bottom: 100%; - top: auto; - margin: 0px 0px -4px -4px; - } - &--open &__info { - visibility: visible; - width:200px; - overflow: visible; - } - } \ No newline at end of file + height: 1rem; + &:first-child { + display: inline-block; + } + display: inline-block; + position: relative; + &:not(.defra-toggletip-target) { + padding-right: 26px; + } + &--open { + z-index: 99; + } + &__container { + position: absolute; + top: -3px; + @include mq ($from: tablet) { + top: -1px; + } + right: 0px; + width: 26px; + height: 26px; + } + &__button { + position: absolute; + top: 0px; + left: 0px; + width: 26px; + height: 26px; + background-color: white; + border: 0px; + padding: 0px; + text-align: center; + color: $govuk-text-colour; + cursor: help; + &-icon { + pointer-events: none; + position: absolute; + overflow: visible; + top: 5px; + left: 5px; + width: 16px; + height: 16px; + border-radius: 100%; + } + &-text { + @include defra-visually-hidden(); + } + svg { + position: relative; + margin: -1px 0px 0px -1px; + } + &:hover, &:focus { + color: govuk-colour('black'); + } + &:hover span { + box-shadow: 0 0 0 5px govuk-colour('light-grey'); + } + &:focus { + outline: 3px solid transparent; + span { + box-shadow: 0 0 0 1px govuk-colour('black'), 0 0 0 5px $govuk-focus-colour; + } + } + } + &__info { + @include govuk-font($size: 16); + cursor: auto; + position:absolute; + width:0px; + overflow: hidden; + box-sizing: border-box; + visibility: hidden; + top: auto; + bottom: 100%; + left: 0px; + padding-bottom: 10px; + text-align: left; + } + &__text { + position: relative; + display:block; + box-sizing: border-box; + padding: 7.5px 10px; + color: govuk-colour('black'); + background: currentcolor; + border: 2px solid currentcolor; + z-index: 2; + span { + color: white; + } + } + &__arrow { + position: absolute; + box-sizing: border-box; + z-index: 1; + width: 10px; + height: 10px; + left: 50%; + bottom: auto; + top: 100%; + margin: -15px 0px 0px -5px; + color: govuk-colour('black'); + border: 5px solid currentcolor; + -webkit-transform: rotate(135deg); + -moz-transform: rotate(135deg); + -o-transform: rotate(135deg); + transform: rotate(135deg); + } + &--bottom &__info { + bottom: auto; + top: 100%; + padding-top: 10px; + padding-bottom: 0px; + } + &--bottom &__arrow { + bottom: 100%; + top: auto; + margin: 0px 0px -15px -5px; + } + &--open &__info { + visibility: visible; + width:200px; + overflow: visible; + } + &.defra-toggletip-target { + cursor: help; + border-bottom: 1px dashed govuk-colour('black'); + padding-bottom: 1px; + outline: 3px solid transparent; + &:focus, &:hover:focus-visible { + border-bottom: 1px solid govuk-colour('black'); + box-shadow: 0 2px 0 govuk-colour('black'), 0 6px 0 govuk-colour('yellow'); + } + &:focus:not(:focus-visible):not(:hover) { + border-bottom: 1px dashed govuk-colour('black'); + box-shadow: none; + } + &:hover { + border-bottom: 1px solid govuk-colour('black'); + box-shadow: 0 2px 0 govuk-colour('black'); + } + } +} diff --git a/server/src/sass/objects/_typography.scss b/server/src/sass/objects/_typography.scss index b81ef5e89..9a3dba80d 100644 --- a/server/src/sass/objects/_typography.scss +++ b/server/src/sass/objects/_typography.scss @@ -2,14 +2,21 @@ mark { background-color: transparent; font-weight: bold; color: inherit; - } - +} +.govuk-caption-s { + @extend .govuk-caption-m; + @include govuk-font($size: 16); +} +.govuk-caption-xs { + @extend .govuk-caption-m; + @include govuk-font($size: 14); +} +// below to be removed once no longer needed .defra-flood-heading-image { display: inline-block; vertical-align: middle; margin-right:2px; } - // Abbr consistent behavior abbr { text-decoration:none; diff --git a/server/src/templates/info-live.html b/server/src/templates/info-live.html index 97398167a..44c988bf6 100644 --- a/server/src/templates/info-live.html +++ b/server/src/templates/info-live.html @@ -31,7 +31,7 @@
- {% if model.type === 'C' %}Tide{% elif model.type === 'G' %}Groundwater{% else %}{{ model.river }}{% endif %} at + {% if model.type === 'C' %}Sea Level{% elif model.type === 'G' %}Groundwater{% else %}{{ model.river }}{% endif %} at {{ model.name }} {% if model.iswales %} (Natural Resources Wales){% endif %} @@ -53,6 +53,21 @@ {{ model.value | round(2) }}m
+ {% if model.value and model.type !== 'R' and model.status !== 'Closed' and model.status !== 'Suspended' and not model.iswales %} +
+
Trend
+
+ Trend + + {% if model.trend %} + {{ model.trend | capitalize }} + {% else %} + n/a + {% endif %} + +
+
+ {% endif %} {% if model.value and model.type !== 'C' and model.status !== 'Closed' and model.status !== 'Suspended' and not model.iswales %}
State
@@ -73,7 +88,7 @@ {% endif %} {% if model.status !== 'Closed' and model.status !== 'Suspended' and model.value %} -

Latest reading: {{ model.date }}

+

Latest at {{ model.date }}

{% endif %} {% if model.up or model.down %}
diff --git a/server/src/templates/key-live.html b/server/src/templates/key-live.html index ac2fb3d83..a3c3de0ca 100644 --- a/server/src/templates/key-live.html +++ b/server/src/templates/key-live.html @@ -87,7 +87,7 @@
diff --git a/server/views/partials/level-row.html b/server/views/partials/level-row.html index f3b4f9bc5..28b3e71fe 100644 --- a/server/views/partials/level-row.html +++ b/server/views/partials/level-row.html @@ -31,15 +31,12 @@ {% if item.group_type == 'rainfall' %} {{ item.one_hr_total }}mm - last hour {{ item.six_hr_total }}mm - last 6hrs {{ item.day_total }}mm - last 24hrs @@ -64,6 +61,20 @@ n/a {% endif %} + + {% if item.trend %} + + + + + + + {{ item.trend }} + + {% else %} + n/a + {% endif %} + {% if item.state %} {{ item.state }} diff --git a/server/views/rainfall-station.html b/server/views/rainfall-station.html index 2587dbe21..291630202 100644 --- a/server/views/rainfall-station.html +++ b/server/views/rainfall-station.html @@ -59,33 +59,41 @@

This measuring s
-
-

- Recent rainfall up to {{ model.latestTimeFormatted }}, {{ model.latestDayFormatted }} -

+
+
+

+ Totals up to {{ model.latestTimeFormatted }} on {{ model.latestDayFormatted }} +

+
-
+
1 hour
- {{ model.telemetryRainfall.latest1hr }}mm + + {{ model.telemetryRainfall.latest1hr }}mm +
-
+
6 hours
- {{ model.telemetryRainfall.latest6hr }}mm + + {{ model.telemetryRainfall.latest6hr }}mm +
-
+
24 hours
- {{ model.telemetryRainfall.latest24hr }}mm + + {{ model.telemetryRainfall.latest24hr }}mm +
@@ -97,15 +105,15 @@

This measuring s

{% endif %}
- {% include "partials/social.html" %} {% include "partials/context-footer.html" %} + {% include "partials/social.html" %} {% include "partials/related-content.html" %}
diff --git a/server/views/river-and-sea-levels.html b/server/views/river-and-sea-levels.html index 34cb424e7..f063e0721 100644 --- a/server/views/river-and-sea-levels.html +++ b/server/views/river-and-sea-levels.html @@ -75,24 +75,24 @@

Results for {{ model.q }}, showing {{ model.queryGroup }} levels - + {%- set hideHeader -%} {% if model.queryGroup == 'rainfall' %}style="display:none"{% endif %} {%- endset -%} {%- set hideRainfallHeader -%} {% if model.queryGroup != 'rainfall' %}style="display:none"{% endif %} {%- endset -%} - {% if model.stations %} - - Gauge - 1 hour - 6 hours - 24 hours + + Measuring station + 1 hour + 6 hours + 24 hours - - Gauge - Height - State + + Measuring station + Height + Trend + State @@ -100,7 +100,6 @@

{% include "partials/level-row.html" %} {% endfor %} - {% endif %}

diff --git a/server/views/station.html b/server/views/station.html index 277348ce7..904e2413f 100644 --- a/server/views/station.html +++ b/server/views/station.html @@ -118,31 +118,54 @@

This data feed w

{% endif %} -

Station summary

-
-
- {# if station has hasPercentiles, this should exclude Coastal #} - {% if model.station.hasPercentiles and not model.station.isCoastal %} -
-
State
-
- {{ model.station.state }} - {{ model.station.stateInformation}} -
-
- {% endif %} -
+
+
+

+ Latest at {{ model.station.recentValue.formattedTime }} on {{ model.station.recentValue.latestDayFormatted }} +

+
+
+
Height
+ {% if model.station.isRiver and model.recentValueBelowZero %} ≤ 0m {% else %} {{ (model.station.recentValue._).toFixed(2) }}m {% endif %} - at {{ model.station.recentValue.dateWhen }} + +
+
+ {% if model.station.trend %} +
+
+ Trend +
+
+ + {{ model.station.trend | capitalize }} +
+ {% endif %} + {# if station has hasPercentiles, this should exclude Coastal #} + {% if model.station.hasPercentiles and not model.station.isCoastal %} +
+
State
+
+ + {{ model.station.state | capitalize }} + +
+
+ {% endif %}
+ {% if model.station.hasPercentiles and not model.station.isCoastal %} +

+ Normal range {{ model.station.stateInformation}} +

+ {% endif %}
@@ -196,7 +219,8 @@

There's a proble

-Download height data CSV ({% if model.isFfoi %}16{% else %}12{% endif %}KB) +Download height data CSV ({% if model.isFfoi %}16{% else %}12{% endif %}KB) + {% endif %} {# Impacts and thresholds #} diff --git a/test/data/stationCoastal.json b/test/data/stationCoastal.json index b927fd2fb..58a8c9efa 100644 --- a/test/data/stationCoastal.json +++ b/test/data/stationCoastal.json @@ -2445,6 +2445,42 @@ "err": false } ], + "river":[ + { + "river_id":"Sea Levels", + "river_name":"Sea Levels", + "river_qualified_name":null, + "navigable":false, + "view_rank":2, + "rank":null, + "rloi_id":3252, + "up":null, + "down":null, + "telemetry_id":"45127", + "region":"South West", + "catchment":"Exe", + "wiski_river_name":"South Devon Coast", + "agency_name":"Exmouth", + "external_name":"Exmouth", + "station_type":"C", + "status":"Active", + "qualifier":"u", + "iswales":false, + "value":"0.888", + "value_timestamp":"2023-03-06T04:00:00.000Z", + "value_erred":false, + "trend":"rising", + "percentile_5":null, + "percentile_95":null, + "centroid":"0101000020E610000039C5AB6DDF640BC005C892A9F24E4940", + "lon":-3.424254280857579, + "lat":50.616780468626565, + "day_total":null, + "six_hr_total":null, + "one_hr_total":null, + "id":"1063" + } + ], "impacts":[], "warningsAlerts":[] } diff --git a/test/data/stationRiver.json b/test/data/stationRiver.json index 5cf732675..225712b9a 100644 --- a/test/data/stationRiver.json +++ b/test/data/stationRiver.json @@ -78,6 +78,7 @@ "value":"0.805", "value_timestamp":"2020-07-13T12:00:00.000Z", "value_erred":false, + "trend":"steady", "percentile_5":"2.84", "percentile_95":"0.353", "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", @@ -85,4 +86,4 @@ "lat":50.8828385361225 }, "warningsAlerts":[] -} \ No newline at end of file +} diff --git a/test/data/toggleTipBelowZeroStation.json b/test/data/toggleTipBelowZeroStation.json new file mode 100644 index 000000000..2f3adb136 --- /dev/null +++ b/test/data/toggleTipBelowZeroStation.json @@ -0,0 +1,88 @@ +{ + "station":{ + "rloi_id":1001, + "station_type":"S", + "qualifier":"u", + "telemetry_context_id":"1364571", + "telemetry_id":"E9140", + "wiski_id":"253110011", + "post_process":true, + "subtract":"0.66", + "region":"Southern", + "area":"Solent and South Downs", + "catchment":"Adur", + "display_region":"South East", + "display_area":"Solent and South Downs", + "display_catchment":"Adur and Ouse", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "location_info":"Upper Beeding", + "x_coord_actual":519204, + "y_coord_actual":110626, + "actual_ngr":"", + "x_coord_display":519204, + "y_coord_display":110626, + "site_max":"4", + "wiski_river_name":"River Adur", + "date_open":"1998-01-01T00:00:00.000Z", + "stage_datum":"5.66", + "period_of_record":"to date", + "por_max_value":"3.35", + "date_por_max":"2013-12-06T01:45:00.000Z", + "highest_level":"4.007", + "date_highest_level":"2013-12-06T02:00:00.000Z", + "por_min_value":"0", + "date_por_min":"2005-03-21T04:30:00.000Z", + "percentile_5":"2.84", + "percentile_95":"0.353", + "comments":"", + "status":"Active", + "status_reason":"", + "status_date":"2019-01-16T12:22:00.000Z", + "coordinates":"{\"type\":\"Point\",\"coordinates\":[-0.306835309255374,50.8828385361225]}", + "geography":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940" + }, + "telemetry":[ + { + "_":-2.805, + "err":false, + "ts":"2020-07-13T12:00Z" + }, + { + "_":-3.805, + "err":false, + "ts":"2020-07-13T11:45Z" + } + ], + "impacts":[], + "river":{ + "river_id":"river-adur", + "river_name":"River Adur", + "navigable":true, + "view_rank":3, + "rank":2, + "rloi_id":1001, + "up":1006, + "down":1032, + "telemetry_id":"E9140", + "region":"Southern", + "catchment":"Adur", + "wiski_river_name":"River Adur", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "station_type":"S", + "status":"Active", + "qualifier":"u", + "iswales":false, + "value":"0.805", + "value_timestamp":"2020-07-13T12:00:00.000Z", + "value_erred":false, + "percentile_5":"2.84", + "percentile_95":"0.353", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "lon":-0.306835309255374, + "lat":50.8828385361225 + }, + "warningsAlerts":[] +} diff --git a/test/data/toggleTipRiverBedStation.json b/test/data/toggleTipRiverBedStation.json new file mode 100644 index 000000000..6debb7c2b --- /dev/null +++ b/test/data/toggleTipRiverBedStation.json @@ -0,0 +1,88 @@ +{ + "station":{ + "rloi_id":1001, + "station_type":"S", + "qualifier":"u", + "telemetry_context_id":"1364571", + "telemetry_id":"E9140", + "wiski_id":"253110011", + "post_process":true, + "subtract":"0.66", + "region":"Southern", + "area":"Solent and South Downs", + "catchment":"Adur", + "display_region":"South East", + "display_area":"Solent and South Downs", + "display_catchment":"Adur and Ouse", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "location_info":"Upper Beeding", + "x_coord_actual":519204, + "y_coord_actual":110626, + "actual_ngr":"", + "x_coord_display":519204, + "y_coord_display":110626, + "site_max":"4", + "wiski_river_name":"River Adur", + "date_open":"1998-01-01T00:00:00.000Z", + "stage_datum":"5.6", + "period_of_record":"to date", + "por_max_value":"3.35", + "date_por_max":"2013-12-06T01:45:00.000Z", + "highest_level":"4.007", + "date_highest_level":"2013-12-06T02:00:00.000Z", + "por_min_value":"0", + "date_por_min":"2005-03-21T04:30:00.000Z", + "percentile_5":"2.84", + "percentile_95":"0.353", + "comments":"", + "status":"Active", + "status_reason":"", + "status_date":"2019-01-16T12:22:00.000Z", + "coordinates":"{\"type\":\"Point\",\"coordinates\":[-0.306835309255374,50.8828385361225]}", + "geography":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940" + }, + "telemetry":[ + { + "_":3.805, + "err":false, + "ts":"2020-07-13T12:00Z" + }, + { + "_":0.805, + "err":false, + "ts":"2020-07-13T11:45Z" + } + ], + "impacts":[], + "river":{ + "river_id":"river-adur", + "river_name":"River Adur", + "navigable":true, + "view_rank":3, + "rank":2, + "rloi_id":1001, + "up":1006, + "down":1032, + "telemetry_id":"E9140", + "region":"Southern", + "catchment":"Adur", + "wiski_river_name":"River Adur", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "station_type":"S", + "status":"Active", + "qualifier":"u", + "iswales":false, + "value":"0.805", + "value_timestamp":"2020-07-13T12:00:00.000Z", + "value_erred":false, + "percentile_5":"2.84", + "percentile_95":"0.353", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "lon":-0.306835309255374, + "lat":50.8828385361225 + }, + "warningsAlerts":[] +} diff --git a/test/data/toggleTipSeaLevelStation.json b/test/data/toggleTipSeaLevelStation.json new file mode 100644 index 000000000..13087fc14 --- /dev/null +++ b/test/data/toggleTipSeaLevelStation.json @@ -0,0 +1,88 @@ +{ + "station":{ + "rloi_id":1001, + "station_type":"S", + "qualifier":"u", + "telemetry_context_id":"1364571", + "telemetry_id":"E9140", + "wiski_id":"253110011", + "post_process":true, + "subtract":"0.66", + "region":"Southern", + "area":"Solent and South Downs", + "catchment":"Adur", + "display_region":"South East", + "display_area":"Solent and South Downs", + "display_catchment":"Adur and Ouse", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "location_info":"Upper Beeding", + "x_coord_actual":519204, + "y_coord_actual":110626, + "actual_ngr":"", + "x_coord_display":519204, + "y_coord_display":110626, + "site_max":"4", + "wiski_river_name":"River Adur", + "date_open":"1998-01-01T00:00:00.000Z", + "stage_datum":"0", + "period_of_record":"to date", + "por_max_value":"3.35", + "date_por_max":"2013-12-06T01:45:00.000Z", + "highest_level":"4.007", + "date_highest_level":"2013-12-06T02:00:00.000Z", + "por_min_value":"0", + "date_por_min":"2005-03-21T04:30:00.000Z", + "percentile_5":"2.84", + "percentile_95":"0.353", + "comments":"", + "status":"Active", + "status_reason":"", + "status_date":"2019-01-16T12:22:00.000Z", + "coordinates":"{\"type\":\"Point\",\"coordinates\":[-0.306835309255374,50.8828385361225]}", + "geography":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940" + }, + "telemetry":[ + { + "_":0.805, + "err":false, + "ts":"2020-07-13T12:00Z" + }, + { + "_":0.805, + "err":false, + "ts":"2020-07-13T11:45Z" + } + ], + "impacts":[], + "river":{ + "river_id":"river-adur", + "river_name":"River Adur", + "navigable":true, + "view_rank":3, + "rank":2, + "rloi_id":1001, + "up":1006, + "down":1032, + "telemetry_id":"E9140", + "region":"Southern", + "catchment":"Adur", + "wiski_river_name":"River Adur", + "agency_name":"Beeding Bridge", + "external_name":"Beeding Bridge", + "station_type":"S", + "status":"Active", + "qualifier":"u", + "iswales":false, + "value":"0.805", + "value_timestamp":"2020-07-13T12:00:00.000Z", + "value_erred":false, + "percentile_5":"2.84", + "percentile_95":"0.353", + "centroid":"0101000020E6100000CCA1A09030A3D3BFB42568DA00714940", + "lon":-0.306835309255374, + "lat":50.8828385361225 + }, + "warningsAlerts":[] +} diff --git a/test/models/rainfall.js b/test/models/rainfall.js index 699c157a6..3f70e1093 100644 --- a/test/models/rainfall.js +++ b/test/models/rainfall.js @@ -64,7 +64,7 @@ lab.experiment('Rainfall model test', () => { const Result = viewModel - Code.expect(Result.latestDayFormatted).to.equal('9th February') + Code.expect(Result.latestDayFormatted).to.equal('9 February') Code.expect(Result.latestTimeFormatted).to.equal('9:15am') }) lab.test('Test station id constructed correctly', async () => { diff --git a/test/models/river-and-sea-levels.js b/test/models/river-and-sea-levels.js index 4bf1218a1..6b0992900 100644 --- a/test/models/river-and-sea-levels.js +++ b/test/models/river-and-sea-levels.js @@ -47,7 +47,7 @@ lab.experiment('river-and-sea-levels model test', () => { const stationsData = data.riverAndSeaLevelData const model = placeViewModel(stationsData) - Code.expect(model.stations[0].latestDatetime).to.equal('Updated 5:30am, 16 July ') + Code.expect(model.stations[0].latestDatetime).to.equal('Latest at 5:30am, 16 July ') }) lab.test('Test river-and-sea-level placeViewModel returns formattedValue with correct number of decimal places', async () => { const stationsData = data.riverAndSeaLevelData diff --git a/test/models/station.js b/test/models/station.js index d40c92a00..6351560c2 100644 --- a/test/models/station.js +++ b/test/models/station.js @@ -29,6 +29,7 @@ lab.experiment('Station model test', () => { Code.expect(Result.station.state).to.equal('Normal') Code.expect(Result.station.stateInformation).to.equal('0.35m to 2.84m') Code.expect(Result.station.status).to.equal('active') + Code.expect(Result.trend).to.equal('steady') Code.expect(Result.banner).to.equal(0) Code.expect(Result.pageTitle).to.equal('River Adur level at Beeding Bridge') Code.expect(Result.dataOverHourOld).to.equal(true) @@ -190,4 +191,37 @@ lab.experiment('Station model test', () => { // 480 telemetry values went in to the model, should be one less Code.expect(Result.telemetry.length).to.equal(479) }) + lab.test('Test station viewModel returns Sea Level Height ToggleTip', async () => { + const stationData = data.toggleTipSeaLevelStation + + const viewModel = new ViewModel(stationData) + + const Result = viewModel + + Code.expect(Result.infoHeight).to.equal('This station measures height from sea level.') + Code.expect(Result.infoTrend).to.equal('The last 2 readings indicate the trend.') + Code.expect(Result.infoState).to.equal('There are 3 states: low, normal and high. The latest level is within the normal range. We calculate the normal range using an average of past measurements and other local factors.') + }) + lab.test('Test station viewModel returns Below Zero Height ToggleTip', async () => { + const stationData = data.toggleTipBelowZeroStation + + const viewModel = new ViewModel(stationData) + + const Result = viewModel + + Code.expect(Result.infoHeight).to.equal('This station measures height from a fixed point on or close to the riverbed. A reading of 0 metres can be normal for some stations because of natural changes to the riverbed.') + Code.expect(Result.infoTrend).to.equal('The last 2 readings indicate the trend.') + Code.expect(Result.infoState).to.equal('There are 3 states: low, normal and high. The latest level is below the normal range. We calculate the normal range using an average of past measurements and other local factors.') + }) + lab.test('Test station viewModel returns River Bed Height ToggleTip', async () => { + const stationData = data.toggleTipRiverBedStation + + const viewModel = new ViewModel(stationData) + + const Result = viewModel + + Code.expect(Result.infoHeight).to.equal('This station measures height from a fixed point on or close to the riverbed.') + Code.expect(Result.infoTrend).to.equal('The last 2 readings indicate the trend.') + Code.expect(Result.infoState).to.equal('There are 3 states: low, normal and high. The latest level is above the normal range. We calculate the normal range using an average of past measurements and other local factors.') + }) }) diff --git a/test/routes/river-and-sea-levels.js b/test/routes/river-and-sea-levels.js index 9d74784f9..2fa5dbf85 100644 --- a/test/routes/river-and-sea-levels.js +++ b/test/routes/river-and-sea-levels.js @@ -478,6 +478,150 @@ lab.experiment('Test - /river-and-sea-levels', () => { Code.expect(response.payload).to.contain('HIGH') Code.expect(response.statusCode).to.equal(200) }) + + lab.test('GET /river-and-sea-levels with trend falling, steady, rising ', async () => { + const floodService = require('../../server/services/flood') + + const fakeIsEngland = () => { + return { is_england: true } + } + + const fakeStationsData = () => [ + { + river_id: 'river-mersey', + river_name: 'River Mersey', + navigable: true, + view_rank: 3, + rank: 5, + rloi_id: 5149, + up: 5052, + down: 5050, + telemetry_id: '693976', + region: 'North West', + catchment: 'Lower Mersey', + wiski_river_name: 'River Mersey', + agency_name: 'Westy', + external_name: 'Westy', + station_type: 'S', + status: 'Active', + qualifier: 'u', + iswales: false, + value: '6.122', + value_timestamp: '2020-02-27T14:30:00.000Z', + value_erred: false, + trend: 'steady', + percentile_5: '4.14', + percentile_95: '3.548', + centroid: '0101000020E6100000DF632687A47B04C09BC5867601B24A40', + lon: -2.56037240587146, + lat: 53.3906696470323 + }, + { + river_id: 'river-mersey', + river_name: 'River Mersey', + navigable: true, + view_rank: 3, + rank: 6, + rloi_id: 5050, + up: 5149, + down: 5084, + telemetry_id: '694063', + region: 'North West', + catchment: 'Lower Mersey', + wiski_river_name: 'River Mersey', + agency_name: 'Fiddlers Ferry', + external_name: 'Fiddlers Ferry', + station_type: 'S', + status: 'Active', + qualifier: 'u', + iswales: false, + value: '3.458', + value_timestamp: '2020-02-27T04:30:00.000Z', + value_erred: false, + trend: 'rising', + percentile_5: '6.2', + percentile_95: '2.611', + centroid: '0101000020E61000001248AD04653A05C01F4188A7E5AF4A40', + lon: -2.65351298955739, + lat: 53.3741959967904 + }, + { + river_id: 'sankey-brook', + river_name: 'Sankey Brook', + navigable: true, + view_rank: 3, + rank: 1, + rloi_id: 5031, + up: null, + down: 5069, + telemetry_id: '694039', + region: 'North West', + catchment: 'Lower Mersey', + wiski_river_name: 'Sankey Brook', + agency_name: 'Causey Bridge', + external_name: 'Causey Bridge', + station_type: 'S', + status: 'Active', + qualifier: 'u', + iswales: false, + value: '0.111', + value_timestamp: '2020-02-27T14:30:00.000Z', + value_erred: false, + trend: 'falling', + percentile_5: '2.5', + percentile_95: '0.209', + centroid: '0101000020E610000095683DBA03FA04C089E4A73671B64A40', + lon: -2.62207742214111, + lat: 53.4253300018109 + } + ] + + sandbox.stub(floodService, 'getIsEngland').callsFake(fakeIsEngland) + sandbox.stub(floodService, 'getStationsWithin').callsFake(fakeStationsData) + + const fakeGetJson = () => data.warringtonGetJson + + const util = require('../../server/util') + sandbox.stub(util, 'getJson').callsFake(fakeGetJson) + + 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?q=Warrington' + } + + const response = await server.inject(options) + + const root = parse(response.payload) + + checkTitleAndDescription( + root, + 'Warrington - Find river, sea, groundwater and rainfall levels - GOV.UK', + 'Find river, sea, groundwater and rainfall levels in Warrington. Check the last updated height and state recorded by the gauges.' + ) + + Code.expect(response.payload).to.contain('falling') + Code.expect(response.payload).to.contain('steady') + Code.expect(response.payload).to.contain('rising') + Code.expect(response.statusCode).to.equal(200) + }) + lab.test('GET /river-and-sea-levels station status Closed', async () => { const floodService = require('../../server/services/flood') diff --git a/test/routes/station.js b/test/routes/station.js index 39ba11b8a..4aa931fda 100644 --- a/test/routes/station.js +++ b/test/routes/station.js @@ -81,11 +81,9 @@ lab.experiment('Test - /station/{id}', () => { } } - const today = new Date() - const fakeTelemetryData = () => [ { - ts: today, + ts: '2022-02-08T08:30:00.000Z', _: 3.589, err: false, formattedTime: '6:00am', @@ -174,7 +172,7 @@ lab.experiment('Test - /station/{id}', () => { geom: '0101000020E61000004F04711E4E60B6BFCA6B257497E44940', coordinates: '{"type":"Point","coordinates":[-0.087407,51.785872]}', comment: 'Property Flooding - Harts Horns Pub', - shortname: 'Floodining at pub', + shortname: 'Flooding at pub', description: 'Flooding at pub on Hornsmill Road', type: 'Property Impact', obsfloodyear: null, @@ -347,17 +345,19 @@ lab.experiment('Test - /station/{id}', () => { value: '9.567', value_timestamp: '2020-03-17T04:30:00.000Z', value_erred: false, + trend: 'steady', percentile_5: '3.5', percentile_95: '0.15', centroid: '0101000020E61000001A741ED88C7105C0755D915F5FE04A40', lon: -2.68044442027032, - lat: 53.7529105624953 + lat: 53.7529105624953, + id: '2695' } } const fakeTelemetryData = () => [ { - ts: '2020-03-13T01:30Z', + ts: '2022-02-08T08:30:00.000Z', _: 1.354, err: false } @@ -401,11 +401,12 @@ lab.experiment('Test - /station/{id}', () => { Code.expect(response.statusCode).to.equal(200) Code.expect(response.payload).to.contain('River Ribble level at Walton-Le-Dale - GOV.UK') Code.expect(response.payload).to.contain('Normal') + Code.expect(response.payload).to.contain('Steady') Code.expect(response.payload).to.contain('0.15m to 3.50m') Code.expect(response.payload).to.contain('Nearby levels') Code.expect(response.payload).to.contain('Upstream') Code.expect(response.payload).to.contain('

Share this page

') - Code.expect(response.payload).to.contain('Download height data CSV (12KB)') + Code.expect(response.payload).to.contain('Download height data CSV (12KB)') }) lab.test('GET station/2042/downstream ', async () => { const floodService = require('../../server/services/flood') @@ -480,11 +481,13 @@ lab.experiment('Test - /station/{id}', () => { value: '0.341', value_timestamp: '2020-03-18T08:00:00.000Z', value_erred: false, + trend: 'steady', percentile_5: '0.659', percentile_95: '0.098', centroid: '0101000020E61000003F2646D543C5F2BF161F852994324A40', lon: -1.17316039381184, - lat: 52.3951465511329 + lat: 52.3951465511329, + id: '2695' } } @@ -610,11 +613,13 @@ lab.experiment('Test - /station/{id}', () => { value: '9.567', value_timestamp: '2020-03-17T04:30:00.000Z', value_erred: false, + trend: 'falling', percentile_5: '3.5', percentile_95: '0.15', centroid: '0101000020E61000001A741ED88C7105C0755D915F5FE04A40', lon: -2.68044442027032, - lat: 53.7529105624953 + lat: 53.7529105624953, + id: '2695' } } @@ -664,7 +669,8 @@ lab.experiment('Test - /station/{id}', () => { Code.expect(response.statusCode).to.equal(200) Code.expect(response.payload).to.contain('River Ribble level at Walton-Le-Dale - GOV.UK') Code.expect(response.payload).to.contain('High') - Code.expect(response.payload).to.contain('') + Code.expect(response.payload).to.contain('Falling') + Code.expect(response.payload).to.contain('Latest at 1:30am') Code.expect(response.payload).to.contain('Nearby levels') Code.expect(response.payload).to.contain('Upstream') Code.expect(response.payload).to.not.contain('Go downstream') @@ -835,11 +841,13 @@ lab.experiment('Test - /station/{id}', () => { value: '9.567', value_timestamp: '2020-03-17T04:30:00.000Z', value_erred: false, + trend: 'rising', percentile_5: '3.5', percentile_95: '0.15', centroid: '0101000020E61000001A741ED88C7105C0755D915F5FE04A40', lon: -2.68044442027032, - lat: 53.7529105624953 + lat: 53.7529105624953, + id: '2695' } } @@ -889,7 +897,8 @@ lab.experiment('Test - /station/{id}', () => { Code.expect(response.statusCode).to.equal(200) Code.expect(response.payload).to.contain('River Ribble level at Walton-Le-Dale - GOV.UK') Code.expect(response.payload).to.contain('Low\n') - Code.expect(response.payload).to.contain('') + Code.expect(response.payload).to.contain('Rising') + Code.expect(response.payload).to.contain('Latest at 1:30am') Code.expect(response.payload).to.contain('Nearby levels') Code.expect(response.payload).to.contain('Upstream') }) @@ -1021,7 +1030,7 @@ lab.experiment('Test - /station/{id}', () => { Code.expect(response.statusCode).to.equal(200) Code.expect(response.payload).to.contain('Sea level at Bude - GOV.UK') - Code.expect(response.payload).to.contain('at ') + Code.expect(response.payload).to.contain('Latest at 6:00am') Code.expect(response.payload).to.contain('3.59m') }) lab.test('GET station/7333 ffoi no max value ', async () => { @@ -1075,12 +1084,11 @@ lab.experiment('Test - /station/{id}', () => { } // const yesterday = moment().subtract(1, 'days').startOf('day') - const today = new Date() const fakeTelemetryData = () => [ { // ts: yesterday, - ts: today, + ts: '2022-02-08T08:30:00.000Z', _: 3.589, err: false, formattedTime: '6:00am', @@ -1320,8 +1328,7 @@ lab.experiment('Test - /station/{id}', () => { } } - // const yesterday = moment().subtract(1, 'days').startOf('day') - const today = moment.tz('Europe/London').add(30, 'm').toDate() + const today = new Date().toString() const formattedDate = moment.tz(today, 'Europe/London').format('h:mma') @@ -1610,7 +1617,7 @@ lab.experiment('Test - /station/{id}', () => { const fakeTelemetryData = () => [ { - ts: newTime, + ts: '2022-02-08T08:30:00.000Z', _: 1.354, err: false } @@ -1945,6 +1952,6 @@ lab.experiment('Test - /station/{id}', () => { Code.expect(response.payload).to.contain('Nearby levels') Code.expect(response.payload).to.contain('Upstream') Code.expect(response.payload).to.contain('

Share this page

') - Code.expect(response.payload).to.contain('Download height data CSV (12KB)') + Code.expect(response.payload).to.contain('Download height data CSV (12KB)') }) }) diff --git a/test/services/flood.js b/test/services/flood.js index 472a37ab3..3efbaf136 100644 --- a/test/services/flood.js +++ b/test/services/flood.js @@ -223,13 +223,13 @@ lab.experiment('Flood service test', () => { sandbox .mock(util) .expects('getJson') - .withArgs('http://server2/river-station-by-station-id/5031') + .withArgs('http://server2/river-station-by-station-id/5031/u') .once() .returns('ok') const floodService = require('../../server/services/flood') - const result = await floodService.getRiverStationByStationId(5031) + const result = await floodService.getRiverStationByStationId(5031, 'u') Code.expect(result).to.equal('ok') })