From b8d973fb0748e403bbad580c00e766a4a73650a3 Mon Sep 17 00:00:00 2001 From: Sam Carlton Date: Sat, 7 May 2022 12:26:17 -0500 Subject: [PATCH] Test that video preload data is valid --- test/helpers/head.js | 97 ++++++++++++++++++++++++++++++++++++ test/listings/index.js | 108 ++++++++++++----------------------------- 2 files changed, 127 insertions(+), 78 deletions(-) create mode 100644 test/helpers/head.js diff --git a/test/helpers/head.js b/test/helpers/head.js new file mode 100644 index 0000000..d6415db --- /dev/null +++ b/test/helpers/head.js @@ -0,0 +1,97 @@ +import { + isValidHttpUrl, + isValidImageUrl, + isNonEmptyString, + isPositiveNumberString +} from '~/helpers/check-types.js' + +export const headPropertyTypes = { + 'meta[charset]': { + charset: isNonEmptyString + }, + + // + 'meta[name="viewport"]': { + content: isNonEmptyString + }, + + // + 'meta[property="og:image"]': { + content: isValidImageUrl + }, + + // + 'meta[property="og:image:width"]': { + content: isPositiveNumberString + }, + + // + 'meta[property="og:image:height"]': { + content: isPositiveNumberString + }, + + // + 'meta[property="og:image:alt"]': { + content: isNonEmptyString + }, + + // + 'meta[property="twitter:card"]': { + content: isNonEmptyString + }, + + // + 'meta[property="twitter:title"]': { + content: isNonEmptyString + }, + + // + 'meta[property="twitter:description"]': { + content: isNonEmptyString + }, + + // + 'meta[property="twitter:url"]': { + content: isValidHttpUrl + }, + + // + 'meta[property="twitter:image"]': { + content: isValidImageUrl, + }, + + // + 'meta[name="description"]': { + content: isNonEmptyString + }, + + // + 'meta[property="twitter:title"]': { + content: isNonEmptyString + }, + + // + 'link[rel="icon"]': { + href: isNonEmptyString + }, + + // + // + // + // + // + 'link[rel="preconnect"]': { + href: isValidHttpUrl + }, + + // + 'link[rel="preload"]': { + as: isNonEmptyString, + href: isValidHttpUrl, + media: isNonEmptyString, + imagesrcset: isNonEmptyString, + type: isNonEmptyString, + + count: false + }, +} diff --git a/test/listings/index.js b/test/listings/index.js index 2a83675..e36f88d 100644 --- a/test/listings/index.js +++ b/test/listings/index.js @@ -4,16 +4,13 @@ import test from 'ava' import axios from 'axios' import { JSDOM } from 'jsdom' -import { - isValidHttpUrl, - isValidImageUrl, - isNonEmptyString, - isPositiveNumberString -} from '~/helpers/check-types.js' + import { makeApiPathFromEndpoint, + getVideoImages, ListingDetails } from '~/helpers/listing-page.js' +import { headPropertyTypes } from '~/test/helpers/head.js' import { PageHead } from '~/helpers/config.js' @@ -24,18 +21,21 @@ const listingsCases = { '/app/spotify': { endpoint: '/app/spotify', apiEndpointPath: '/api/app/spotify.json', + expectInitialVideo: true, }, // Electron '/app/electron-framework': { endpoint: '/app/electron-framework', apiEndpointPath: '/api/app/electron-framework.json', + expectInitialVideo: false, }, // Express VPN Benchmarks '/app/expressvpn/benchmarks/': { endpoint: '/app/expressvpn/benchmarks/', apiEndpointPath: '/api/app/expressvpn.json', + expectInitialVideo: true, } } @@ -85,7 +85,6 @@ function parseHTML ( htmlString ) { test( 'Listings have valid api endpoints', async t => { const { listingsDetails } = t.context - for ( const [ caseEndpoint, listingCase ] of listingCaseEntries ) { const apiPath = listingsDetails[ caseEndpoint ].apiEndpointPath @@ -94,86 +93,39 @@ test( 'Listings have valid api endpoints', async t => { } }) +test( 'Listings with videos have preload data for initialVideo', async t => { + const { listingsDetails } = t.context -const headPropertyTypes = { - 'meta[charset]': { - charset: isNonEmptyString - }, + for ( const [ caseEndpoint, listingCase ] of listingCaseEntries ) { - // - 'meta[name="viewport"]': { - content: isNonEmptyString - }, + const listingDetails = listingsDetails[ caseEndpoint ] - // - 'meta[property="og:image"]': { - content: isValidImageUrl - }, + t.assert( listingDetails.hasInitialVideo === listingCase.expectInitialVideo, `${ caseEndpoint } has initial video` ) - // - 'meta[property="og:image:width"]': { - content: isPositiveNumberString - }, + // Stop here if we don't have an initial video + if ( !listingDetails.hasInitialVideo ) continue - // - 'meta[property="og:image:height"]': { - content: isPositiveNumberString - }, + // t.log('listingDetails.initialVideo', listingDetails.initialVideo) - // - 'meta[property="og:image:alt"]': { - content: isNonEmptyString - }, + // Get headProperties for image preloading + const preloadHeadChecks = headPropertyTypes[ 'link[rel="preload"]' ] - // - 'meta[property="twitter:card"]': { - content: isNonEmptyString - }, + const images = getVideoImages( listingDetails.initialVideo ) - // - 'meta[property="twitter:title"]': { - content: isNonEmptyString - }, + // Check if the head object properties are correct + for ( const preload of images.preloads ) { + for ( const [ propertyName, checkMethod ] of Object.entries( preloadHeadChecks ) ) { + // Skip count property + if ( propertyName === 'count' ) continue - // - 'meta[property="twitter:description"]': { - content: isNonEmptyString - }, + const value = preload[ propertyName ] - // - 'meta[property="twitter:url"]': { - content: isValidHttpUrl - }, + t.assert( checkMethod( value ), `${ propertyName } failed. Value is '${ value }' for '${ images.imgSrc }'` ) + } + } + } +}) - // - 'meta[property="twitter:image"]': { - content: isValidImageUrl, - }, - - // - 'meta[name="description"]': { - content: isNonEmptyString - }, - - // - 'meta[property="twitter:title"]': { - content: isNonEmptyString - }, - - // - 'link[rel="icon"]': { - href: isNonEmptyString - }, - - // - // - // - // - // - 'link[rel="preconnect"]': { - href: isValidHttpUrl - }, -} test('Listings have valid headings', async t => { const { listingsDetails } = t.context @@ -196,9 +148,9 @@ test('Listings have valid headings', async t => { let count = 1 - if ( has( checks, ['count'] ) ) { + if ( has( checks, 'count' ) ) { count = checks.count - delete checks.count + // delete checks.count } if ( count !== false ) {