diff --git a/examples/nuxt-app/test/features/site/theme.feature b/examples/nuxt-app/test/features/site/theme.feature index c87c36d2da..3583731f94 100644 --- a/examples/nuxt-app/test/features/site/theme.feature +++ b/examples/nuxt-app/test/features/site/theme.feature @@ -54,3 +54,26 @@ Feature: Site theme And the page endpoint for path "/" returns fixture "/landingpage/image-banner" with status 200 Given I visit the page "/" Then the last updated date should not be displayed + + @mockserver + Scenario: Favicon and app icons are set correctly + Given the site endpoint returns fixture "/site/reference" with status 200 + And the page endpoint for path "/" returns fixture "/landingpage/image-banner" with status 200 + Given I visit the page "/" + And the site should include the following meta tags + | name | value | + | theme-color | #6B19A3 | + And the site should include the following link tags + | name | value | + | icon | /placeholders/logo.png | + | apple-touch-icon | /placeholders/medium.png | + And the sites manifest should include the following details + | key | value | + | name | Test site | + | short_name | Testing | + | description | About my test site | + | theme_color | #6B19A3 | + | background_color | #ffffff | + And the sites manifest should include the following icons + | url | sizes | + | /placeholders/medium.png | any | diff --git a/examples/nuxt-app/test/fixtures/site/reference.json b/examples/nuxt-app/test/fixtures/site/reference.json index 5e968c0573..19e97701d1 100644 --- a/examples/nuxt-app/test/fixtures/site/reference.json +++ b/examples/nuxt-app/test/fixtures/site/reference.json @@ -1,6 +1,22 @@ { "name": "Test site", + "shortName": "Testing", + "slogan": "

About my test site

", "acknowledgementHeader": "Test hero acknowledgement", + "favicon": { + "src": "/placeholders/logo.png", + "alt": "", + "title": "", + "width": 192, + "height": 192 + }, + "appIcon": { + "src": "/placeholders/medium.png", + "alt": "", + "title": "", + "width": 512, + "height": 512 + }, "acknowledgementFooter": "Test footer acknowledgement", "socialImages": { "twitter": {}, diff --git a/packages/nuxt-ripple/components/TideBaseLayout.vue b/packages/nuxt-ripple/components/TideBaseLayout.vue index 127e820deb..db09e57c4c 100644 --- a/packages/nuxt-ripple/components/TideBaseLayout.vue +++ b/packages/nuxt-ripple/components/TideBaseLayout.vue @@ -173,5 +173,5 @@ await nuxtApp.callHook('tide:page', props) useTideSiteTheme(props.site) useTideHideAlerts() useTideSiteMeta(props, nuxtApp?.$app_origin) -useTideFavicons() +useTideFavicons(props.site) diff --git a/packages/nuxt-ripple/composables/use-tide-favicons.ts b/packages/nuxt-ripple/composables/use-tide-favicons.ts index 1776f44920..acdacd7137 100644 --- a/packages/nuxt-ripple/composables/use-tide-favicons.ts +++ b/packages/nuxt-ripple/composables/use-tide-favicons.ts @@ -1,44 +1,45 @@ -export default () => { - const theme = useAppConfig().ripple?.theme +import { TideSiteData } from '../types' - useHead({ - link: [ - { - rel: 'apple-touch-icon', - sizes: '180x180', - href: '/apple-touch-icon.png' - }, - { - rel: 'icon', - type: 'image/png', - sizes: '32x32', - href: '/favicon-32x32.png' - }, - { - rel: 'icon', - type: 'image/png', - sizes: '16x16', - href: '/favicon-16x16.png' - }, - { rel: 'manifest', href: '/site.webmanifest' }, +export default (site: TideSiteData) => { + const theme = useAppConfig()?.ripple?.theme + const { public: config } = useRuntimeConfig() + + let link = [] + const favicon = site.favicon?.src ?? '/favicon.png' + const appIcon = site.appIcon?.src ?? '/app-icon.png' + const themeColour = theme?.['rpl-clr-primary'] ?? '#ffffff' + + const manifest = { + id: config?.siteUrl, + name: site?.name, + short_name: site?.shortName, + description: site?.slogan?.replace(/<[^>]*>/g, ''), + start_url: config?.siteUrl, + icons: [ { - rel: 'mask-icon', - href: '/safari-pinned-tab.svg', - color: - theme && theme.hasOwnProperty('rpl-clr-primary') - ? theme['rpl-clr-primary'] - : '#0054c9' + src: appIcon, + sizes: 'any' } ], - meta: [ - { - name: 'msapplication-TileColor', - content: - theme && theme.hasOwnProperty('rpl-clr-primary') - ? theme['rpl-clr-primary'] - : '#0054c9' - }, - { name: 'theme-color', content: '#ffffff' } - ] + theme_color: themeColour, + background_color: '#ffffff', + display: 'standalone' + } + + link.push({ + rel: 'apple-touch-icon', + href: appIcon + }) + + link.push({ + rel: 'manifest', + href: `data:application/manifest+json,${encodeURIComponent(JSON.stringify(manifest))}` }) + + link.push({ + rel: 'icon', + href: favicon + }) + + useHead({ link, meta: [{ name: 'theme-color', content: themeColour }] }) } diff --git a/packages/nuxt-ripple/mapping/site/index.ts b/packages/nuxt-ripple/mapping/site/index.ts index 595cd8945a..ec433636ea 100644 --- a/packages/nuxt-ripple/mapping/site/index.ts +++ b/packages/nuxt-ripple/mapping/site/index.ts @@ -1,6 +1,7 @@ import { getImageFromField, getBody, + getBodyFromField, getLinkFromField, getSiteKeyValues, TideSiteApi @@ -14,9 +15,13 @@ import processSiteSocialLinks from '../utils/processSiteSocialLinks.js' export default { mapping: { name: 'name', + shortName: 'field_short_name', _src: (src: any) => process.env.NODE_ENV === 'development' ? src : undefined, siteAlerts: siteAlertsMapping, + slogan: (src: any) => getBodyFromField(src, 'field_site_slogan'), + favicon: (src: any) => getImageFromField(src, 'field_site_favicon'), + appIcon: (src: any) => getImageFromField(src, 'field_site_app_icon'), siteLogo: (src: any) => { if (src.field_site_logo) { return { @@ -114,6 +119,8 @@ export default { }, includes: [ ...siteAlertsIncludes, + 'field_site_favicon', + 'field_site_app_icon', 'field_site_og_image', 'field_site_og_image.field_media_image', 'field_site_twitter_image', diff --git a/packages/nuxt-ripple/public/android-chrome-192x192.png b/packages/nuxt-ripple/public/android-chrome-192x192.png deleted file mode 100644 index 19e560c0ac..0000000000 Binary files a/packages/nuxt-ripple/public/android-chrome-192x192.png and /dev/null differ diff --git a/packages/nuxt-ripple/public/android-chrome-512x512.png b/packages/nuxt-ripple/public/android-chrome-512x512.png deleted file mode 100644 index 0ee3346778..0000000000 Binary files a/packages/nuxt-ripple/public/android-chrome-512x512.png and /dev/null differ diff --git a/packages/nuxt-ripple/public/app-icon.png b/packages/nuxt-ripple/public/app-icon.png new file mode 100644 index 0000000000..cdae6c10a6 Binary files /dev/null and b/packages/nuxt-ripple/public/app-icon.png differ diff --git a/packages/nuxt-ripple/public/apple-touch-icon.png b/packages/nuxt-ripple/public/apple-touch-icon.png deleted file mode 100644 index 3250b474db..0000000000 Binary files a/packages/nuxt-ripple/public/apple-touch-icon.png and /dev/null differ diff --git a/packages/nuxt-ripple/public/browserconfig.xml b/packages/nuxt-ripple/public/browserconfig.xml deleted file mode 100644 index 7fa0279f0f..0000000000 --- a/packages/nuxt-ripple/public/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #0054c9 - - - diff --git a/packages/nuxt-ripple/public/favicon-16x16.png b/packages/nuxt-ripple/public/favicon-16x16.png deleted file mode 100644 index 331a2e9b28..0000000000 Binary files a/packages/nuxt-ripple/public/favicon-16x16.png and /dev/null differ diff --git a/packages/nuxt-ripple/public/favicon.ico b/packages/nuxt-ripple/public/favicon.ico deleted file mode 100644 index 5a0d507110..0000000000 Binary files a/packages/nuxt-ripple/public/favicon.ico and /dev/null differ diff --git a/packages/nuxt-ripple/public/favicon-32x32.png b/packages/nuxt-ripple/public/favicon.png similarity index 100% rename from packages/nuxt-ripple/public/favicon-32x32.png rename to packages/nuxt-ripple/public/favicon.png diff --git a/packages/nuxt-ripple/public/mstile-150x150.png b/packages/nuxt-ripple/public/mstile-150x150.png deleted file mode 100644 index c0eb987f00..0000000000 Binary files a/packages/nuxt-ripple/public/mstile-150x150.png and /dev/null differ diff --git a/packages/nuxt-ripple/public/safari-pinned-tab.svg b/packages/nuxt-ripple/public/safari-pinned-tab.svg deleted file mode 100644 index 36f574825c..0000000000 --- a/packages/nuxt-ripple/public/safari-pinned-tab.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - - - - diff --git a/packages/nuxt-ripple/public/site.webmanifest b/packages/nuxt-ripple/public/site.webmanifest deleted file mode 100644 index b20abb7cbb..0000000000 --- a/packages/nuxt-ripple/public/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "", - "short_name": "", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} diff --git a/packages/nuxt-ripple/types.d.ts b/packages/nuxt-ripple/types.d.ts index e8d51cbef2..0d76404c73 100644 --- a/packages/nuxt-ripple/types.d.ts +++ b/packages/nuxt-ripple/types.d.ts @@ -13,6 +13,8 @@ export type TideApiResponse = any export interface TideSiteData { name: string + shortName?: string + slogan?: string _src?: any siteAlerts: TideAlert[] siteLogo: { @@ -21,6 +23,16 @@ export interface TideSiteData { altText: string } showQuickExit: boolean + favicon?: { + src: string + width: string + height: string + } + appIcon?: { + src: string + width: string + height: string + } acknowledgementHeader?: string acknowledgementFooter: string cornerGraphic?: { diff --git a/packages/ripple-test-utils/step_definitions/common/site/theme.ts b/packages/ripple-test-utils/step_definitions/common/site/theme.ts index a315afd956..b014acd5c5 100644 --- a/packages/ripple-test-utils/step_definitions/common/site/theme.ts +++ b/packages/ripple-test-utils/step_definitions/common/site/theme.ts @@ -1,4 +1,4 @@ -import { Given, Then } from '@badeball/cypress-cucumber-preprocessor' +import { DataTable, Given, Then } from '@badeball/cypress-cucumber-preprocessor' import { set } from 'lodash-es' Then( @@ -58,3 +58,70 @@ Given( }) } ) + +Then( + 'the site should include the following meta tags', + (dataTable: DataTable) => { + const table = dataTable.hashes() + + table.forEach((row) => { + cy.get(`meta[name="${row.name}"]`).should( + 'have.attr', + 'content', + row.value + ) + }) + } +) + +Then( + 'the site should include the following link tags', + (dataTable: DataTable) => { + const table = dataTable.hashes() + + table.forEach((row) => { + cy.get(`link[rel="${row.name}"]`).should('have.attr', 'href', row.value) + }) + } +) + +Then( + 'the sites manifest should include the following details', + (dataTable: DataTable) => { + const table = dataTable.hashes() + + cy.get('link[rel="manifest"]') + .invoke('attr', 'href') + .then((href) => { + const manifest = JSON.parse(decodeURIComponent(href.split(',')[1])) + cy.wrap(manifest).as('manifest') + }) + + table.forEach((row) => { + cy.get('@manifest').should('include', { + [row.key]: row.value + }) + }) + } +) + +Then( + 'the sites manifest should include the following icons', + (dataTable: DataTable) => { + const table = dataTable.hashes() + + cy.get('link[rel="manifest"]') + .invoke('attr', 'href') + .then((href) => { + const manifest = JSON.parse(decodeURIComponent(href.split(',')[1])) + cy.wrap(manifest).as('manifest') + }) + + table.forEach((row) => { + cy.get('@manifest').its('icons').should('deep.include', { + src: row.url, + sizes: row.sizes + }) + }) + } +)