From 92de398684c4c774c937b676e344b023a4a7b65c Mon Sep 17 00:00:00 2001 From: Tom Meyer Date: Wed, 15 Dec 2021 08:41:42 -0500 Subject: [PATCH] Revert "Version 1.27" --- .github/workflows/version-update.yml | 52 --- directanswercards/card_component.js | 8 +- global_config.json | 1 - hbshelpers/getDefaultUniversalLimit.js | 27 -- hbshelpers/wrapJsPartial.js | 15 - layouts/html.hbs | 11 +- layouts/preload-fonts.hbs | 8 +- package-lock.json | 309 +++++++++--------- package.json | 6 +- script/core.hbs | 18 +- static/js/answers-experience.js | 4 - static/js/formatters-internal.js | 192 ++++++----- .../generate-cta-field-type-link.js | 5 +- static/js/manual-initializer.js | 3 +- static/package-lock.json | 33 +- static/package.json | 3 +- static/scss/answers-variables.scss | 1 - .../answers/answers-variables-default.scss | 1 - .../sdk-filter-overrides.scss | 5 +- static/scss/answers/theme.scss | 4 - static/webpack-config.js | 33 +- .../common-partials/markup/directanswer.hbs | 1 - .../common-partials/script/directanswer.hbs | 9 - .../markup/directanswer.hbs | 2 +- .../script/directanswer.hbs | 10 +- .../script/universalresults.hbs | 13 + .../vertical-full-page-map/page-config.json | 2 +- templates/vertical-grid/page-config.json | 2 +- templates/vertical-grid/page.html.hbs | 2 +- templates/vertical-map/page-config.json | 2 +- templates/vertical-map/page.html.hbs | 2 +- .../vertical-standard/markup/directanswer.hbs | 1 - templates/vertical-standard/page-config.json | 14 +- templates/vertical-standard/page.html.hbs | 5 +- .../vertical-standard/script/directanswer.hbs | 1 - test-site/config/global_config.json | 1 - test-site/pages-patches/people.html.hbs.patch | 13 +- tests/acceptance/index.js | 2 +- tests/browser-automation/pageoperator.js | 59 ---- tests/browser-automation/testlocations.js | 210 ------------ tests/percy/camera.js | 2 +- .../constants.js | 2 +- tests/percy/index.js | 27 +- tests/percy/multilangphotographer.js | 129 ++++++++ tests/percy/photographer.js | 143 ++++++++ .../queries.json} | 0 .../generate-cta-field-type-link.js | 9 +- .../js/formatters-internal/highlightField.js | 39 --- tests/static/js/formatters-internal/image.js | 72 +++- .../script/fixtures/directanswer.hbs.js | 2 - tests/wcag/index.js | 11 +- tests/wcag/wcagreporter.js | 147 +++++++++ 52 files changed, 852 insertions(+), 821 deletions(-) delete mode 100644 .github/workflows/version-update.yml delete mode 100644 hbshelpers/getDefaultUniversalLimit.js delete mode 100644 hbshelpers/wrapJsPartial.js delete mode 100644 templates/common-partials/markup/directanswer.hbs delete mode 100644 templates/common-partials/script/directanswer.hbs delete mode 100644 templates/vertical-standard/markup/directanswer.hbs delete mode 100644 templates/vertical-standard/script/directanswer.hbs delete mode 100644 tests/browser-automation/pageoperator.js delete mode 100644 tests/browser-automation/testlocations.js rename tests/{browser-automation => percy}/constants.js (97%) create mode 100644 tests/percy/multilangphotographer.js create mode 100644 tests/percy/photographer.js rename tests/{browser-automation/multilangqueries.json => percy/queries.json} (100%) delete mode 100644 tests/static/js/formatters-internal/highlightField.js delete mode 100644 tests/templates/script/fixtures/directanswer.hbs.js create mode 100644 tests/wcag/wcagreporter.js diff --git a/.github/workflows/version-update.yml b/.github/workflows/version-update.yml deleted file mode 100644 index e4a944be6..000000000 --- a/.github/workflows/version-update.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Update package version for release & hotfix branches - -on: - push: - branches: [release/*, hotfix/*] - -permissions: - contents: write - pull-requests: write - -jobs: - update-version: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - - name: update package version - id: vars - run: | - BRANCH_NAME="${GITHUB_REF#refs/heads/}" - PACKAGE_VERSION="${GITHUB_REF##*/}" - echo ::set-output name=branch::${BRANCH_NAME} - if [[ $PACKAGE_VERSION =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] - then - if [[ $PACKAGE_VERSION =~ ^v[0-9]+\.[0-9]+$ ]] - then - PACKAGE_VERSION="${PACKAGE_VERSION}.0" - fi - echo ::set-output name=version::${PACKAGE_VERSION} - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - if npm version ${PACKAGE_VERSION} | tee >( grep -q 'npm ERR! Version not changed' ) - then - echo "Package version is already in sync with branch name." - echo ::set-output name=should_create_pr::0 - exit 0 - fi - echo ::set-output name=should_create_pr::1 - git push -u origin HEAD:"dev/update-version-${PACKAGE_VERSION}" - else - echo "Branch name ${BRANCH_NAME} does not have the correct format with package version." - exit 1 - fi - - name: create version update pr - if: steps.vars.outputs.should_create_pr == 1 - uses: repo-sync/pull-request@v2 - with: - source_branch: "dev/update-version-${{ steps.vars.outputs.version }}" - destination_branch: "${{ steps.vars.outputs.branch }}" - pr_title: "Update Package Version to ${{ steps.vars.outputs.version }}" - pr_body: "*An automated PR which updates the version number in package.json and package-lock.json files*" - github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/directanswercards/card_component.js b/directanswercards/card_component.js index 0fadc0462..5593bf584 100644 --- a/directanswercards/card_component.js +++ b/directanswercards/card_component.js @@ -23,9 +23,9 @@ BaseDirectAnswerCard["{{componentName}}"] = class extends ANSWERS.Component { setState(data) { let cardData = this.dataForRender(this.type, this.answer, this.relatedItem, this.snippet); this.validateDataForRender(cardData); + return super.setState({ ...cardData, - searcher: data.searcher, feedbackEnabled: ANSWERS.getAnalyticsOptIn(), feedbackSubmitted: data.feedbackSubmitted, isArray: Array.isArray(this.answer.value), @@ -97,7 +97,7 @@ BaseDirectAnswerCard["{{componentName}}"] = class extends ANSWERS.Component { .addOptions({ directAnswer: true, verticalKey: this.verticalConfigId, - searcher: this.getState('searcher'), + searcher: 'UNIVERSAL', entityId: this.associatedEntityId }); @@ -120,7 +120,7 @@ BaseDirectAnswerCard["{{componentName}}"] = class extends ANSWERS.Component { */ addDefaultEventOptions(eventOptions = {}) { return Object.assign({}, { - searcher: this.getState('searcher'), + searcher: "UNIVERSAL", verticalConfigId: this.verticalConfigId, entityId: this.associatedEntityId, ...eventOptions @@ -144,7 +144,7 @@ BaseDirectAnswerCard["{{componentName}}"] = class extends ANSWERS.Component { verticalKey: this.verticalConfigId, directAnswer: true, fieldName: this.answer.fieldApiName, - searcher: this.getState('searcher'), + searcher: 'UNIVERSAL', entityId: this.associatedEntityId, url: event.target.href }; diff --git a/global_config.json b/global_config.json index f1dfe4cc5..6211fd20e 100644 --- a/global_config.json +++ b/global_config.json @@ -3,7 +3,6 @@ // "token": "", // The auth token to access Answers experience. // "apiKey": "", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system // "experienceVersion": "", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system - // "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox') // "businessId": "", // The business ID of the account. This will be provided automatically by the Yext CI system // "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations. // "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build output and the token must be specified through manual initialization. diff --git a/hbshelpers/getDefaultUniversalLimit.js b/hbshelpers/getDefaultUniversalLimit.js deleted file mode 100644 index b63f0abe6..000000000 --- a/hbshelpers/getDefaultUniversalLimit.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Generates a default result limit for each vertical on the universal page. The - * default is taken from the vertical's `universalLimit`, specified in the related - * page's VTC. If there is no such `universalLimit`, the back-end default of 10 will - * be used. - * - * @param {Object} pageConfigs - The configurations for each page. - * @returns {Object} The partial of the search configuration related to universal limits. - */ - module.exports = function getDefaultUniversalLimit(pageConfigs) { - const universalLimit = Object.entries(pageConfigs) - .filter(([pageName, _]) => pageName != 'index') - .reduce((limit, [_, pageConfig]) => { - const verticalKey = pageConfig.verticalKey; - const hasUniversalLimit = - pageConfig.verticalsToConfig && - pageConfig.verticalsToConfig[verticalKey] && - pageConfig.verticalsToConfig[verticalKey].universalLimit; - if (hasUniversalLimit) { - limit[verticalKey] = pageConfig.verticalsToConfig[verticalKey].universalLimit; - } - - return limit; - }, {}); - - return { universalLimit }; -} \ No newline at end of file diff --git a/hbshelpers/wrapJsPartial.js b/hbshelpers/wrapJsPartial.js deleted file mode 100644 index 42df79482..000000000 --- a/hbshelpers/wrapJsPartial.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This is a block helper for injecting inline JS using handlebars. - * - * First, it wraps the statement in an iife to prevent namespacing issues. - * - * Then, it adds an extra new line to the end of the iife. - * This is necesssary because handlebars removes the first new line it sees after a partial invocation, - * which can result in certain js parsing issues, for example if the last line of the partial is a - * single line js comment, the line immediately after the partial will be included in the comment. - * - * @param {import('handlebars').HelperOptions} opts - */ -module.exports = function wrapJsPartial(opts) { - return `(() => { \n${opts.fn()}\n })()\n`; -} \ No newline at end of file diff --git a/layouts/html.hbs b/layouts/html.hbs index ad1446197..2abe7f518 100644 --- a/layouts/html.hbs +++ b/layouts/html.hbs @@ -6,9 +6,7 @@ if (window.name == 'overlay') { window.isOverlay = true; } - {{#wrapJsPartial}} - {{> script/translations}} - {{/wrapJsPartial}} + {{> script/translations}} {{/babel}} {{> layouts/headincludes }} @@ -74,15 +72,10 @@ diff --git a/static/js/answers-experience.js b/static/js/answers-experience.js index 9e4450cce..9b528ac0f 100644 --- a/static/js/answers-experience.js +++ b/static/js/answers-experience.js @@ -22,10 +22,6 @@ export default class AnswersExperience { this._registerRuntimeConfigListeners(); } - init() { - console.error('AnswersExperience.init was called before an init method was set. This is a no-op.') - } - /** * Registers runtime config listeners and ensures that they execute * after Answers has initialized diff --git a/static/js/formatters-internal.js b/static/js/formatters-internal.js index 113e82b79..a468ec024 100644 --- a/static/js/formatters-internal.js +++ b/static/js/formatters-internal.js @@ -11,7 +11,6 @@ import { isChrome } from './useragent.js'; import LocaleCurrency from 'locale-currency' import getSymbolFromCurrency from 'currency-symbol-map' import { parseLocale } from './utils.js'; -import escape from 'escape-html'; export function address(profile) { if (!profile.address) { @@ -282,107 +281,134 @@ export function joinList(list, separator) { return list.join(separator); } -/** - * Given an image object with a url, changes the url to use dynamic thumbnailer and https. - * - * Note: A dynamic thumbnailer url generated with atLeastAsLarge = true returns an image that is - * at least as large in one dimension of the desired size. In other words, the returned image will - * be at least as large, and as close as possible to, the largest image that is contained within a - * box of the desired size dimensions. - * - * If atLeastAsLarge = false, the dynamic thumbnailer url will give the largest image that is - * smaller than the desired size in both dimensions. - * - * @param {Object} simpleOrComplexImage An image object with a url - * @param {string} desiredSize The desired size of the image ('x') - * @param {boolean} atLeastAsLarge Whether the image should be at least as large as the desired - * size in one dimension or smaller than the desired size in both - * dimensions. - * @returns {Object} An object with a url for dynamic thumbnailer +/* + * Given object with url and alternateText, changes url to use https */ -export function image(simpleOrComplexImage = {}, desiredSize = '200x', atLeastAsLarge = true) { - let image = simpleOrComplexImage.image || simpleOrComplexImage; - if (!image) { +export function image(simpleOrComplexImage = {}, size = '200x', atLeastAsLarge = true) { + let img = simpleOrComplexImage.image || simpleOrComplexImage; + if (!img) { return {}; } - if (!image.url) { - return image; - } - if (!(Object.prototype.toString.call(image).indexOf('Object') > 0)) { - throw new Error("Expected parameter of type Map"); - } - if ((typeof desiredSize !== 'string') || (desiredSize == null)) { - throw new Error(`Object of type string expected. Got ${typeof desiredSize}.`); - } - if (desiredSize.indexOf('x') === -1) { - throw new Error("Invalid desired size"); - } - if ((typeof atLeastAsLarge !== 'boolean') || (atLeastAsLarge == null)) { - throw new Error(`Object of type boolean expected. Got ${typeof atLeastAsLarge}.`); + + if (!img.url) { + return img; } - let desiredWidth, desiredHeight; - let desiredDims = desiredSize.split('x'); + function imageBySizeEntity(image, desiredSize, atLeastAsLarge = true) { + if ((image == null) || !(Object.prototype.toString.call(image).indexOf('Object') > 0)) { + throw new Error("Expected parameter of type Map"); + } + if ((typeof desiredSize !== 'string') || (desiredSize == null)) { + throw new Error(`Object of type string expected. Got ${typeof desiredSize}.`); + } + if (desiredSize.indexOf('x') === -1) { + throw new Error("Invalid desired size"); + } + if ((typeof atLeastAsLarge !== 'boolean') || (atLeastAsLarge == null)) { + throw new Error(`Object of type boolean expected. Got ${typeof atLeastAsLarge}.`); + } - const [urlWithoutExtension, extension] = _splitStringOnIndex(image.url, image.url.lastIndexOf('.')); - const [urlBeforeDimensions, dimensions] = _splitStringOnIndex(urlWithoutExtension, urlWithoutExtension.lastIndexOf('/') + 1); - const fullSizeDims = dimensions.split('x'); + if (!image.thumbnails) { + image.thumbnails = []; + } - if (desiredDims[0] !== '') { - desiredWidth = Number.parseInt(desiredDims[0]); - if (Number.isNaN(desiredWidth)) { - throw new Error("Invalid width specified"); + if (!Array.isArray(image.thumbnails)) { + throw new Error(`Object of type array expected. Got ${typeof image.thumbnails}.`); } - } else { - desiredWidth = atLeastAsLarge ? 1 : Number.parseInt(fullSizeDims[0]); - } - if (desiredDims[1] !== '') { - desiredHeight = Number.parseInt(desiredDims[1]); - if (Number.isNaN(desiredHeight)) { - throw new Error("Invalid height specified"); + if (image.width != undefined && image.height != undefined && image.url != undefined) { + image.thumbnails.push({ + 'width': image.width, + 'height': image.height, + 'url': image.url + }); } - } else { - desiredHeight = atLeastAsLarge ? 1 : Number.parseInt(fullSizeDims[1]); - } - const urlWithDesiredDims = urlBeforeDimensions + desiredWidth + 'x' + desiredHeight + extension; + let desiredWidth, desiredHeight; + let desiredDims = desiredSize.split('x'); - const dynamicUrl = atLeastAsLarge - ? _replaceUrlHost(urlWithDesiredDims, 'dynl.mktgcdn.com') - : _replaceUrlHost(urlWithDesiredDims, 'dynm.mktgcdn.com'); + if (desiredDims[0] !== '') { + desiredWidth = Number.parseInt(desiredDims[0]); + if (Number.isNaN(desiredWidth)) { + throw new Error("Invalid width specified"); + } + } + + if (desiredDims[1] !== '') { + desiredHeight = Number.parseInt(desiredDims[1]); + if (Number.isNaN(desiredHeight)) { + throw new Error("Invalid height specified"); + } + } + const thumbnails = image.thumbnails + .filter(thumb => thumb.width && thumb.height) + .sort((a, b) => b.width - a.width); + return atLeastAsLarge + ? _getSmallestThumbnailOverThreshold(thumbnails, desiredWidth, desiredHeight) + : _getLargestThumbnailUnderThreshold(thumbnails, desiredWidth, desiredHeight); + } + + const result = imageBySizeEntity(img, size, atLeastAsLarge); return Object.assign( {}, - image, + img, { - url: dynamicUrl.replace('http://', 'https://') + url: result.replace('http://', 'https://') } ); } /** - * Splits a string into two parts at the specified index. - * - * @param {string} str The string to be split - * @param {number} index The index at which to split the string - * @returns {Array} The two parts of the string after splitting + * Gets the smallest thumbnail that is over the min width and min height. + * If no thumbnails are over the given thresholds, will return the closest one. + * + * This method assumes all thumbnails have the same aspect ratio, and that + * thumbnails are sorted in descending size. + * + * @param {Array<{{url: string, width: number, height: number}}>} thumbnails + * @param {number|undefined} minWidth + * @param {number|undefined} minHeight + * @returns {string} */ -function _splitStringOnIndex(str, index) { - return [str.slice(0, index), str.slice(index)]; +function _getSmallestThumbnailOverThreshold(thumbnails, minWidth, minHeight) { + let index = thumbnails.length - 1; + while (index > 0) { + const thumb = thumbnails[index]; + const widthOverThreshold = minWidth ? thumb.width >= minWidth : true; + const heightOverThreshold = minHeight ? thumb.height >= minHeight : true; + if (widthOverThreshold && heightOverThreshold) { + return thumb.url + } + index--; + } + return thumbnails[0].url; } /** - * Replaces the current host of a url with the specified host. + * Gets the largest thumbnail that is under the max width and max height. + * If no thumbnails are under the given thresholds, will return the closest one. * - * @param {string} url The url whose host is to be changed - * @param {string} host The new host to change to - * @returns {string} The url updated with the specified host + * This method assumes all thumbnails have the same aspect ratio, and that + * thumbnails are sorted in descending size. + * + * @param {Array<{{url: string, width: number, height: number}}>} thumbnails + * @param {number|undefined} maxWidth + * @param {number|undefined} maxHeight + * @returns {string} */ -function _replaceUrlHost(url, host) { - const splitUrl = url.split('://'); - const urlAfterHost = splitUrl[1].slice(splitUrl[1].indexOf('/')); - return splitUrl[0] + '://' + host + urlAfterHost; +function _getLargestThumbnailUnderThreshold(thumbnails, maxWidth, maxHeight) { + let index = 0; + while (index < thumbnails.length) { + const thumb = thumbnails[index]; + const widthOverThreshold = maxWidth ? thumb.width <= maxWidth : true; + const heightOverThreshold = maxHeight ? thumb.height <= maxHeight : true; + if (widthOverThreshold && heightOverThreshold) { + return thumb.url + } + index++; + } + return thumbnails[thumbnails.length - 1].url; } /** @@ -541,20 +567,20 @@ export function priceRange(defaultPriceRange, countryCode) { * highlight. */ export function highlightField(fieldValue, matchedSubstrings = []) { - let highlightedString = ''; + let highlightedString = fieldValue; - // We must first sort the matchedSubstrings by ascending offset. + // We must first sort the matchedSubstrings by decreasing offset. const sortedMatches = matchedSubstrings.slice() - .sort((match1, match2) => match1.offset - match2.offset); + .sort((match1, match2) => match2.offset - match1.offset); - let processedFieldValueIndex = 0; sortedMatches.forEach(match => { const { offset, length } = match; - highlightedString += escape(fieldValue.substring(processedFieldValueIndex, offset)) - + `${escape(fieldValue.substring(offset, offset + length))}`; - processedFieldValueIndex = offset + length; + highlightedString = + highlightedString.substr(0, offset) + + `${fieldValue.substr(offset, length)}`+ + highlightedString.substr(offset + length); }); - highlightedString += escape(fieldValue.substring(processedFieldValueIndex)); + return highlightedString; } diff --git a/static/js/formatters/generate-cta-field-type-link.js b/static/js/formatters/generate-cta-field-type-link.js index 03710d452..8b8ce6aec 100644 --- a/static/js/formatters/generate-cta-field-type-link.js +++ b/static/js/formatters/generate-cta-field-type-link.js @@ -1,9 +1,6 @@ import CtaFormatter from '@yext/cta-formatter'; /** - * By default, the linkType is assumed to be 'URL', which does not apply additional formatting, as opposed - * to the "Phone" and "Email" linkTypes. - * * @param {{link: string, linkType: string}} cta the Calls To Action field object * @returns {string} The formatted url associated with the Call to Action object if the cta object exists, null otherwise */ @@ -13,7 +10,7 @@ export function generateCTAFieldTypeLink(cta) { } const normalizedCTA = { ...cta, - linkType: normalizeCtaLinkType(cta.linkType || 'URL') + linkType: normalizeCtaLinkType(cta.linkType) } return CtaFormatter.generateCTAFieldTypeLink(normalizedCTA); } diff --git a/static/js/manual-initializer.js b/static/js/manual-initializer.js index aa25d6d43..7776ab547 100644 --- a/static/js/manual-initializer.js +++ b/static/js/manual-initializer.js @@ -1,6 +1,5 @@ /** - * Responsible for setting up manual initialization of the experience. - * Sets the "init" method of the {@link AnswersExperience} on the window. + * Responsible for setting up manual initialization of the experience */ export default class ManualInitializer { /** diff --git a/static/package-lock.json b/static/package-lock.json index a14deae29..5ba5f8a57 100644 --- a/static/package-lock.json +++ b/static/package-lock.json @@ -1,6 +1,6 @@ { "name": "answers-hitchhiker-theme", - "version": "1.27.0", + "version": "1.26.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2877,11 +2877,6 @@ "integrity": "sha512-DR6NO3h9niOT+MZs7bjxlj2a1k+POu5RN8CLTPX2+i78bRi9eLe7+0zXgUHMnGXWybYcL61E9hGhPKqedy8tQA==", "dev": true }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -4303,26 +4298,6 @@ "ms": "2.1.2" } }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "simple-git": { "version": "2.46.0", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.46.0.tgz", @@ -4333,12 +4308,6 @@ "@kwsites/promise-deferred": "^1.1.1", "debug": "^4.3.1" } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true } } }, diff --git a/static/package.json b/static/package.json index 33077004e..456946b07 100644 --- a/static/package.json +++ b/static/package.json @@ -1,6 +1,6 @@ { "name": "answers-hitchhiker-theme", - "version": "1.27.0", + "version": "1.26.0", "description": "Toolchain for use with the HH Theme", "main": "Gruntfile.js", "scripts": { @@ -49,7 +49,6 @@ "@vimeo/player": "^2.15.3", "core-js": "^3.6.5", "css-vars-ponyfill": "^2.3.1", - "escape-html": "^1.0.3", "file-system": "^2.2.2", "fs-extra": "^8.1.0", "iframe-resizer": "^4.1.1", diff --git a/static/scss/answers-variables.scss b/static/scss/answers-variables.scss index 380b018c4..ff509225d 100644 --- a/static/scss/answers-variables.scss +++ b/static/scss/answers-variables.scss @@ -51,7 +51,6 @@ $container-width: 1000px; --yxt-searchbar-button-text-color-hover: var(--yxt-color-brand-primary); --yxt-filter-options-options-max-height: none; --yxt-filters-and-sorts-font-size: var(--yxt-font-size-md); - --yxt-filter-options-option-label-line-height: 20px; --yxt-alternative-verticals-emphasized-font-weight: var(--yxt-font-weight-semibold); --yxt-text-snippet-highlight-color: #eef3fb; --yxt-text-snippet-font-color: var(--yxt-color-text-primary); diff --git a/static/scss/answers/answers-variables-default.scss b/static/scss/answers/answers-variables-default.scss index 24e487bfd..7dfefb3d6 100644 --- a/static/scss/answers/answers-variables-default.scss +++ b/static/scss/answers/answers-variables-default.scss @@ -50,7 +50,6 @@ $container-width: 1000px; --yxt-searchbar-button-text-color-hover: var(--yxt-color-brand-primary); --yxt-filter-options-options-max-height: none; --yxt-filters-and-sorts-font-size: var(--yxt-font-size-md); - --yxt-filter-options-option-label-line-height: 20px; --yxt-alternative-verticals-emphasized-font-weight: var(--yxt-font-weight-semibold); --yxt-text-snippet-highlight-color: #eef3fb; --yxt-text-snippet-font-color: var(--yxt-color-text-primary); diff --git a/static/scss/answers/collapsible-filters/sdk-filter-overrides.scss b/static/scss/answers/collapsible-filters/sdk-filter-overrides.scss index 44a9765cd..75f74d44d 100644 --- a/static/scss/answers/collapsible-filters/sdk-filter-overrides.scss +++ b/static/scss/answers/collapsible-filters/sdk-filter-overrides.scss @@ -23,9 +23,8 @@ } &-options { - margin: 0; - padding-top: 4px; - padding-bottom: 4px; + margin-top: 4px; + margin-bottom: 4px; padding-left: 4px; } diff --git a/static/scss/answers/theme.scss b/static/scss/answers/theme.scss index 41ecbe3f7..30b59e43d 100644 --- a/static/scss/answers/theme.scss +++ b/static/scss/answers/theme.scss @@ -194,10 +194,6 @@ font-size: var(--yxt-filters-and-sorts-font-size); } - .yxt-FilterOptions-optionLabel { - line-height: var(--yxt-filter-options-option-label-line-height); - } - .yxt-Card-child { mark { background-color: unset; diff --git a/static/webpack-config.js b/static/webpack-config.js index 6fae95617..a1e3fcce8 100644 --- a/static/webpack-config.js +++ b/static/webpack-config.js @@ -143,11 +143,42 @@ module.exports = function () { } ], }, + { + test: /\.html$/i, + use: [ + { + loader: 'html-loader', + options: { + sources: { + list: [ + { + tag: 'link', + attribute: 'href', + type: 'src', + filter: (tag, attribute, attributes) => { + const isPreload = attributes.find(attr => { + return attr.name === 'rel' && attr.value === 'preload'; + }); + const isFont = attributes.find(attr => { + return attr.name === 'as' && attr.value === 'font'; + }); + return isPreload && isFont; + } + } + ], + urlFilter: (attribute, value) => { + return /^[./]*static\/assets\//.test(value); + } + }, + } + } + ] + }, { test: /\.(png|ico|gif|jpe?g|svg|webp|eot|otf|ttf|woff2?)$/, type: 'asset/resource', generator: { - filename: '[name][ext]' + filename: '[name].[hash].[ext]' } } ], diff --git a/templates/common-partials/markup/directanswer.hbs b/templates/common-partials/markup/directanswer.hbs deleted file mode 100644 index 5f000c6a7..000000000 --- a/templates/common-partials/markup/directanswer.hbs +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/templates/common-partials/script/directanswer.hbs b/templates/common-partials/script/directanswer.hbs deleted file mode 100644 index 7d383bd9a..000000000 --- a/templates/common-partials/script/directanswer.hbs +++ /dev/null @@ -1,9 +0,0 @@ -ANSWERS.addComponent("DirectAnswer", -{{#shallowMergeConfig}}[ - { - "container": "#js-answersDirectAnswer" - }, - {{{json componentSettings.DirectAnswer}}} -] -{{/shallowMergeConfig}} -); diff --git a/templates/universal-standard/markup/directanswer.hbs b/templates/universal-standard/markup/directanswer.hbs index e22487a72..5f000c6a7 100644 --- a/templates/universal-standard/markup/directanswer.hbs +++ b/templates/universal-standard/markup/directanswer.hbs @@ -1 +1 @@ -{{> templates/common-partials/markup/directanswer }} \ No newline at end of file +
\ No newline at end of file diff --git a/templates/universal-standard/script/directanswer.hbs b/templates/universal-standard/script/directanswer.hbs index b9007a58e..7d383bd9a 100644 --- a/templates/universal-standard/script/directanswer.hbs +++ b/templates/universal-standard/script/directanswer.hbs @@ -1 +1,9 @@ -{{> templates/common-partials/script/directanswer }} \ No newline at end of file +ANSWERS.addComponent("DirectAnswer", +{{#shallowMergeConfig}}[ + { + "container": "#js-answersDirectAnswer" + }, + {{{json componentSettings.DirectAnswer}}} +] +{{/shallowMergeConfig}} +); diff --git a/templates/universal-standard/script/universalresults.hbs b/templates/universal-standard/script/universalresults.hbs index 891dd7cd3..6dab2c0d7 100644 --- a/templates/universal-standard/script/universalresults.hbs +++ b/templates/universal-standard/script/universalresults.hbs @@ -88,6 +88,19 @@ ANSWERS.addComponent("UniversalResults", Object.assign({}, { pin: {{> templates/universal-standard/script/map-pin mapConfig }}, }), {{/if}} + {{#if universalLimit}} + transformData: (data) => { + let results = data.results; + if (results) { + results = results.filter((rex, idx) => { + return idx < {{{universalLimit}}}; + }); + } + return Object.assign(data, { + results: results + }); + }, + {{/if}} {{/inline}} {{!-- diff --git a/templates/vertical-full-page-map/page-config.json b/templates/vertical-full-page-map/page-config.json index a7ab84af4..3d5142d4a 100644 --- a/templates/vertical-full-page-map/page-config.json +++ b/templates/vertical-full-page-map/page-config.json @@ -64,7 +64,7 @@ "": { // The vertical key from your search configuration // "label": "", // The name of the vertical in the section header and the navigation bar // "verticalLimit": 15, // The result count limit for vertical search - "universalLimit": 4, // The result count limit for universal search + // "universalLimit": 5, // The result count limit for universal search "cardType": "location-standard", // The name of the card to use - e.g. accordion, location, customcard // "icon": "pin", // The icon to use on the card for this vertical "mapConfig": { diff --git a/templates/vertical-grid/page-config.json b/templates/vertical-grid/page-config.json index 84cc96508..7d1c4279d 100644 --- a/templates/vertical-grid/page-config.json +++ b/templates/vertical-grid/page-config.json @@ -66,7 +66,7 @@ "": { // The vertical key from your search configuration // "label": "", // The name of the vertical in the section header and the navigation bar // "verticalLimit": 15, // The result count limit for vertical search - "universalLimit": 4, // The result count limit for universal search + // "universalLimit": 5, // The result count limit for universal search "cardType": "product-prominentimage", // The name of the card to use - e.g. accordion, location, customcard // "icon": "star", // The icon to use on the card for this vertical "universalSectionTemplate": "standard" diff --git a/templates/vertical-grid/page.html.hbs b/templates/vertical-grid/page.html.hbs index 1362ae503..69ad32d03 100644 --- a/templates/vertical-grid/page.html.hbs +++ b/templates/vertical-grid/page.html.hbs @@ -27,7 +27,6 @@ partial for this page, you should not use it on any other page. --> {{!-- {{> layouts/overlay-suggestions }} --}}
- {{> templates/vertical-grid/markup/spellcheck }}
{{> templates/vertical-grid/markup/verticalresultscount }} {{> templates/vertical-grid/markup/appliedfilters }} @@ -41,6 +40,7 @@ {{!-- {{> templates/vertical-grid/markup/facets }} --}} {{!--
--}}
+ {{> templates/vertical-grid/markup/spellcheck }} {{> templates/vertical-grid/markup/verticalresults }} {{> templates/vertical-grid/markup/pagination }} {{!-- {{> templates/vertical-grid/markup/qasubmission }} --}} diff --git a/templates/vertical-map/page-config.json b/templates/vertical-map/page-config.json index dd5752c7a..21beb8b33 100644 --- a/templates/vertical-map/page-config.json +++ b/templates/vertical-map/page-config.json @@ -66,7 +66,7 @@ "": { // The vertical key from your search configuration // "label": "", // The name of the vertical in the section header and the navigation bar // "verticalLimit": 15, // The result count limit for vertical search - "universalLimit": 4, // The result count limit for universal search + // "universalLimit": 5, // The result count limit for universal search "cardType": "location-standard", // The name of the card to use - e.g. accordion, location, customcard // "icon": "pin", // The icon to use on the card for this vertical "mapConfig": { diff --git a/templates/vertical-map/page.html.hbs b/templates/vertical-map/page.html.hbs index e9e21d377..39991564b 100644 --- a/templates/vertical-map/page.html.hbs +++ b/templates/vertical-map/page.html.hbs @@ -29,7 +29,6 @@ {{!-- {{> layouts/overlay-suggestions }} --}}
- {{> templates/vertical-map/markup/spellcheck }}
{{> templates/vertical-map/markup/verticalresultscount }} {{> templates/vertical-map/markup/appliedfilters }} @@ -43,6 +42,7 @@ {{!-- {{> templates/vertical-map/markup/filterbox }} --}} {{!--
--}}
+ {{> templates/vertical-map/markup/spellcheck }} {{> templates/vertical-map/markup/verticalresults }} {{> templates/vertical-map/markup/pagination }} {{!-- {{> templates/vertical-map/markup/qasubmission }} --}} diff --git a/templates/vertical-standard/markup/directanswer.hbs b/templates/vertical-standard/markup/directanswer.hbs deleted file mode 100644 index e22487a72..000000000 --- a/templates/vertical-standard/markup/directanswer.hbs +++ /dev/null @@ -1 +0,0 @@ -{{> templates/common-partials/markup/directanswer }} \ No newline at end of file diff --git a/templates/vertical-standard/page-config.json b/templates/vertical-standard/page-config.json index 3ae907bc4..7286a26f5 100644 --- a/templates/vertical-standard/page-config.json +++ b/templates/vertical-standard/page-config.json @@ -32,18 +32,6 @@ "clearSearchText": "clear search" // Text when there are no results, conducts an empty search }, **/ - /** - "DirectAnswer": { - "types": { - "FEATURED_SNIPPET": { - "cardType": "documentsearch-standard" - }, - "FIELD_VALUE": { - "cardType": "allfields-standard" - } - } - }, - **/ "AppliedFilters": { "removable": true }, @@ -78,7 +66,7 @@ "": { // The vertical key from your search configuration // "label": "", // The name of the vertical in the section header and the navigation bar // "verticalLimit": 15, // The result count limit for vertical search - "universalLimit": 4, // The result count limit for universal search + // "universalLimit": 5, // The result count limit for universal search "cardType": "standard", // The name of the card to use - e.g. accordion, location, customcard // "icon": "star", // The icon to use on the card for this vertical "universalSectionTemplate": "standard" diff --git a/templates/vertical-standard/page.html.hbs b/templates/vertical-standard/page.html.hbs index 767d24184..d2a4ee93e 100644 --- a/templates/vertical-standard/page.html.hbs +++ b/templates/vertical-standard/page.html.hbs @@ -1,14 +1,12 @@ {{#> layouts/html }} {{#> script/core }} {{> cards/all }} - {{!-- {{> directanswercards/all }} --}} {{!-- {{> templates/vertical-standard/collapsible-filters/page-setup }} --}} {{> templates/vertical-standard/script/appliedfilters }} {{> templates/vertical-standard/script/verticalresultscount }} {{> templates/vertical-standard/script/searchbar }} {{> templates/vertical-standard/script/spellcheck }} {{> templates/vertical-standard/script/navigation }} - {{!-- {{> templates/vertical-standard/script/directanswer }} --}} {{> templates/vertical-standard/script/verticalresults }} {{> templates/vertical-standard/script/pagination }} {{> templates/vertical-standard/script/locationbias }} @@ -29,8 +27,6 @@ partial for this page, you should not use it on any other page. --> {{!-- {{> layouts/overlay-suggestions }} --}}
- {{!-- {{> templates/vertical-standard/markup/directanswer }} --}} - {{> templates/vertical-standard/markup/spellcheck }}
{{> templates/vertical-standard/markup/verticalresultscount }} {{> templates/vertical-standard/markup/appliedfilters }} @@ -44,6 +40,7 @@ {{!-- {{> templates/vertical-standard/markup/facets }} --}} {{!--
--}}
+ {{> templates/vertical-standard/markup/spellcheck }} {{> templates/vertical-standard/markup/verticalresults }} {{> templates/vertical-standard/markup/pagination }} {{!-- {{> templates/vertical-standard/markup/qasubmission }} --}} diff --git a/templates/vertical-standard/script/directanswer.hbs b/templates/vertical-standard/script/directanswer.hbs deleted file mode 100644 index b9007a58e..000000000 --- a/templates/vertical-standard/script/directanswer.hbs +++ /dev/null @@ -1 +0,0 @@ -{{> templates/common-partials/script/directanswer }} \ No newline at end of file diff --git a/test-site/config/global_config.json b/test-site/config/global_config.json index 5d9b812f7..589a13933 100644 --- a/test-site/config/global_config.json +++ b/test-site/config/global_config.json @@ -3,7 +3,6 @@ // "token": "", // The auth token to access Answers experience. "apiKey": "2d8c550071a64ea23e263118a2b0680b", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system // "experienceVersion": "", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system - // "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox') // "businessId": "", // The business ID of the account. This will be provided automatically by the Yext CI system // "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations. // "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build and the token must be specified through the runtime config. diff --git a/test-site/pages-patches/people.html.hbs.patch b/test-site/pages-patches/people.html.hbs.patch index 2b0771874..1f0092700 100644 --- a/test-site/pages-patches/people.html.hbs.patch +++ b/test-site/pages-patches/people.html.hbs.patch @@ -20,7 +20,18 @@ {{!-- {{> templates/vertical-grid/script/filterbox }} --}} {{!-- {{> templates/vertical-grid/script/qasubmission }} --}} {{/script/core }} -@@ -30,15 +30,15 @@ +@@ -22,23 +22,23 @@ + {{> templates/vertical-grid/markup/navigation }} +
+
+- ++ ++ + {{!-- {{> layouts/overlay-suggestions }} --}} +
{{> templates/vertical-grid/markup/verticalresultscount }} {{> templates/vertical-grid/markup/appliedfilters }} diff --git a/tests/acceptance/index.js b/tests/acceptance/index.js index 8ce3bec22..2f4ff8da6 100644 --- a/tests/acceptance/index.js +++ b/tests/acceptance/index.js @@ -31,7 +31,7 @@ runTests(argv.browsers, argv.concurrency); */ async function runTests (browsers, concurrency) { const testcafe = await createTestCafe({ - configFile: './tests/acceptance/testcafe.json' + configFile: './testcafe.json' }); try { const numberTestsFailed = await testcafe.createRunner() diff --git a/tests/browser-automation/pageoperator.js b/tests/browser-automation/pageoperator.js deleted file mode 100644 index 4ca0cb80f..000000000 --- a/tests/browser-automation/pageoperator.js +++ /dev/null @@ -1,59 +0,0 @@ -const { BrowserPageWidths } = require("./constants"); - -/** - * Responsible for browser navigation based on given test locations. - * Each test location is an object which may contain: - * - name: name of this test - * - page: the vertical page to navigate to (if omit, navigate to universal page by default) - * - queryParams: the query params to peform the search on - * - viewport: viewport of the page (if omit, desktop view is used by default) - * - commands: a list of actions to perform on the page by the page navigator - */ -class PageOperator { - /** - * @param {PageNavigator} pageNavigator page navigator - * @param {import('puppeteer').Page} page A Pupeteer Page - * @param {Object[]} testLocations a list of test locations to navigate to - */ - constructor(pageNavigator, page, testLocations) { - this._pageNavigator = pageNavigator; - this._page = page; - this._testLocations = testLocations; - this._testLocationIndex = -1; - } - - hasNextTestLocation() { - return this._testLocationIndex < this._testLocations.length - 1; - } - - async nextTestLocation() { - this._testLocationIndex++; - const testConfig = this._testLocations[this._testLocationIndex]; - await this._setPageViewport(testConfig.viewport); - testConfig.page - ? await this._pageNavigator.gotoVerticalPage(testConfig.page, testConfig.queryParams) - : await this._pageNavigator.gotoUniversalPage(testConfig.queryParams); - await this._executeTestCommands(testConfig.commands); - return testConfig; - } - - async _setPageViewport(viewport) { - if (viewport && !['desktop', 'mobile'].includes(viewport)) { - throw error(`unknown viewport: ${viewport}`); - } - viewport === 'mobile' - ? await this._page.setViewport({ width: BrowserPageWidths.Mobile, height: this._page.viewport().height }) - : await this._page.setViewport({ width: BrowserPageWidths.Desktop, height: this._page.viewport().height }); - } - - async _executeTestCommands(commands) { - if (!commands) { - return; - } - for (const command of commands ) { - await this._pageNavigator[command.type].call(this._pageNavigator, command.params); - } - } -} - -module.exports = PageOperator; diff --git a/tests/browser-automation/testlocations.js b/tests/browser-automation/testlocations.js deleted file mode 100644 index 3141c24b2..000000000 --- a/tests/browser-automation/testlocations.js +++ /dev/null @@ -1,210 +0,0 @@ -const queryConfig = require('./multilangqueries.json'); - -const universalSearchTests = (multilangQueries) => [ - { - name: 'universal-search', - }, - { - name: 'universal-search--no-results', - queryParams: { query: 'a' } - }, - { - name: 'universal-search--spellcheck', - queryParams: { query: 'office sparce' } - }, - { - name: 'universal-search--faq-accordion', - queryParams: { query: multilangQueries.faq }, - commands: [{ type: 'click', params: ['.HitchhikerFaqAccordion-toggle'] }] - }, - { - name: 'universal-search--product-prominentimage', - queryParams: { query: 'yext answers' } - } -]; - -const verticalSearchTests = (multilangQueries) => [ - { - name: 'vertical-search', - page: 'events' - }, - { - name: 'vertical-search--no-results', - page: 'events', - queryParams: { query: 'a' } - }, - { - name: 'vertical-search--spellcheck', - page: 'events', - queryParams: { query: 'vrginia' } - }, - { - name: 'vertical-search--custom-cta-icons', - page: 'events_custom_cta_icons' - }, - { - name: 'vertical-search--financial-professional-location', - page: 'financial_professionals', - queryParams: { query: 'connor' } - }, - { - name: 'vertical-search--healthcare-professional-location', - page: 'healthcare_professionals', - queryParams: { query: 'bob' } - }, - { - name: 'vertical-search--job-standard', - page: 'jobs', - queryParams: { query: multilangQueries.job } - }, - { - name: 'vertical-search--document-standard', - page: 'help_articles', - queryParams: { query: 'slap chop' } - }, - { - name: 'vertical-search--menuitem-standard', - page: 'menu_items', - queryParams: { query: multilangQueries.menu_item } - } -]; - -const verticalGridSearchTests = () => [ - { - name: 'vertical-grid-search', - page: 'people', - queryParams: { query: 'a' } - }, - { - name: 'vertical-grid-search--spellcheck', - page: 'people', - queryParams: { query: 'vrginia' } - }, - { - name: 'vertical-grid-search--product-prominentvideo', - page: 'products', - queryParams: { query: 'yext answers' } - }, - { - name: 'vertical-grid-search--product-prominentimage-clickable', - page: 'products_clickable_image', - queryParams: { query: 'yext answers' } - } -]; - -const verticalMapSearchTests = () => [ - { - name: 'vertical-map-search', - page: 'locations', - queryParams: { query: 'a' } - }, - { - name: 'vertical-map-search--google', - page: 'locations_google', - queryParams: { query: 'virginia' } - } -]; - -const verticalFullPageMapSearchTests = () => [ - { - name: 'vertical-full-page-map__desktop-view', - page: 'locations_full_page_map', - queryParams: { query: '' }, - viewport: 'desktop' - }, - { - name: 'vertical-full-page-map__mobile-list-view', - page: 'locations_full_page_map', - queryParams: { query: '' }, - viewport: 'mobile' - }, - { - name: 'vertical-full-page-map__mobile-map-view', - page: 'locations_full_page_map', - queryParams: { query: '' }, - viewport: 'mobile', - commands: [{ type: 'click', params: ['.Answers-mobileToggle'] }] - }, - { - name: 'vertical-full-page-map__mobile-detail-view', - page: 'locations_full_page_map', - queryParams: { query: '' }, - viewport: 'mobile', - commands: [ - { type: 'click', params: ['.Answers-mobileToggle'] }, - { type: 'click', params: ['.js-answersMap button'] } - ] - }, - { - name: 'vertical-full-page-map--alternative-verticals', - page: 'locations_full_page_map_with_filters', - queryParams: { query: 'people' } - }, - { - name: 'vertical-full-page-map--spellcheck__desktop-view', - page: 'locations_full_page_map', - queryParams: { query: 'office sparce' }, - viewport: 'desktop' - }, - { - name: 'vertical-full-page-map--spellcheck__mobile-list-view', - page: 'locations_full_page_map', - queryParams: { query: 'office sparce' }, - viewport: 'mobile' - }, - { - name: 'vertical-full-page-map--nlp-filters__desktop-view', - page: 'locations_full_page_map', - queryParams: { query: 'virginia' }, - viewport: 'desktop' - }, - { - name: 'vertical-full-page-map-with-filters--nlp-filters__desktop-view', - page: 'locations_full_page_map_with_filters', - queryParams: { query: 'virginia' }, - viewport: 'desktop' - } -]; - -const directAnswersTests = (multilangQueries) => [ - { - name: 'field-direct-answer', - queryParams: { query: multilangQueries.field_direct_answers } - }, - { - name: 'documentsearch-direct-answer', - queryParams: { query: 'where was joe exotic born?' } - }, - { - name: 'documentsearch-rich-text-direct-answer', - queryParams: { query: 'how to get rich text' } - }, - { - name: 'documentsearch-rich-text-picture-direct-answer', - queryParams: { query: 'who is howard?' } - } -]; - -const multilangDirectAnswersTests = (multilangQueries) => [ - { - name: 'field-direct-answer', - queryParams: { query: multilangQueries.field_direct_answers } - } -]; - -/** - * Generate test locations based on the given locale. - * - * @param {string} locale locale of the page - * @returns an array of test locations - */ -const getTestingLocations = (locale='en') => [ - ...universalSearchTests(queryConfig[locale]), - ...verticalSearchTests(queryConfig[locale]), - ...verticalGridSearchTests(), - ...verticalMapSearchTests(), - ...verticalFullPageMapSearchTests(), - ...(locale === 'en' ? directAnswersTests(queryConfig[locale]) : multilangDirectAnswersTests(queryConfig[locale])) -] - -module.exports = getTestingLocations; diff --git a/tests/percy/camera.js b/tests/percy/camera.js index 6ffd013a2..12946c3c5 100644 --- a/tests/percy/camera.js +++ b/tests/percy/camera.js @@ -1,4 +1,4 @@ -const { BrowserPageWidths } = require('../browser-automation/constants'); +const { BrowserPageWidths } = require('./constants'); /** * Responsible for taking Percy snapshots diff --git a/tests/browser-automation/constants.js b/tests/percy/constants.js similarity index 97% rename from tests/browser-automation/constants.js rename to tests/percy/constants.js index fabc05622..07c10182a 100644 --- a/tests/browser-automation/constants.js +++ b/tests/percy/constants.js @@ -1,4 +1,4 @@ module.exports.BrowserPageWidths = { Desktop: 1280, Mobile: 375 -} +} \ No newline at end of file diff --git a/tests/percy/index.js b/tests/percy/index.js index 73d4f4b68..952fc79a2 100644 --- a/tests/percy/index.js +++ b/tests/percy/index.js @@ -1,23 +1,24 @@ const HttpServer = require('../test-utils/server'); +const Photographer = require('./photographer'); +const MultilangPhotographer = require('./multilangphotographer'); const StandardPageNavigator = require('./standardpagenavigator'); const IframePageNavigator = require('./iframepagenavigator'); const Camera = require('./camera'); +const queryConfig = require('./queries.json'); const puppeteer = require('puppeteer'); const percySnapshot = require('@percy/puppeteer'); -const PageOperator = require('../browser-automation/pageoperator'); -const getTestingLocations = require('../browser-automation/testlocations'); const PORT = 5042; async function defaultSnapshots(page) { const standardPageNavigator = new StandardPageNavigator(page, `http://localhost:${PORT}`); const standardCamera = new Camera(percySnapshot, page); - await captureSnapshots(standardPageNavigator, page, standardCamera); + await (new Photographer(standardPageNavigator, standardCamera).captureSnapshots()); } async function iframeSnapshots(page) { const iframePageNavigator = new IframePageNavigator(page, `http://localhost:${PORT}`, 'iframe_test'); const iframeCamera = new Camera(percySnapshot, page, true); - await captureSnapshots(iframePageNavigator, page, iframeCamera); + await (new Photographer(iframePageNavigator, iframeCamera).captureSnapshots()); } async function spanishSnapshots(page) { @@ -25,7 +26,7 @@ async function spanishSnapshots(page) { const standardCamera = new Camera(percySnapshot, page); standardPageNavigator.setCurrentLocale('es'); standardCamera.setLocale('es'); - await captureSnapshots(standardPageNavigator, page, standardCamera, 'es'); + await (new MultilangPhotographer(standardPageNavigator, standardCamera, queryConfig.es).captureSnapshots()); } async function rtlSnapshots(page) { @@ -33,21 +34,7 @@ async function rtlSnapshots(page) { const standardCamera = new Camera(percySnapshot, page); standardPageNavigator.setCurrentLocale('ar'); standardCamera.setLocale('ar'); - await captureSnapshots(standardPageNavigator, page, standardCamera, 'ar'); -} - -async function captureSnapshots(navigator, page, camera, locale='en') { - const operator = new PageOperator(navigator, page, getTestingLocations(locale)); - while (operator.hasNextTestLocation()) { - const testConfig = await operator.nextTestLocation(); - if (testConfig.viewport) { - testConfig.viewport === 'mobile' - ? await camera.snapshotMobileOnly(testConfig.name) - : await camera.snapshotDesktopOnly(testConfig.name); - } else { - await camera.snapshot(testConfig.name); - } - } + await (new MultilangPhotographer(standardPageNavigator, standardCamera, queryConfig.ar).captureSnapshots()); } async function runPercyTest() { diff --git a/tests/percy/multilangphotographer.js b/tests/percy/multilangphotographer.js new file mode 100644 index 000000000..65bf8829e --- /dev/null +++ b/tests/percy/multilangphotographer.js @@ -0,0 +1,129 @@ +/** + * @typedef {import('./pagenavigator.js')} PageNavigator + * @typedef {import('./Camera.js')} Camera + */ + +/** + * Responsible for determining which snapshots to take for specific locale + */ +class MultilangPhotographer { + /** + * @param {PageNavigator} pageNavigator + * @param {Camera} camera + * @param {Object} queries custom queries for specific locale + */ + constructor(pageNavigator, camera, queries) { + this._pageNavigator = pageNavigator; + this._camera = camera; + this._queries = queries; + } + + /** + * Sets custom queries based on locale + * + * @param {Object} queries + */ + setLocaleQueries(queries) { + this._queries = queries; + } + + async captureSnapshots() { + await this._captureUniversalSearch(); + await this._captureVerticalSearch(); + await this._captureVerticalGridSearch(); + await this._captureVerticalMapSearch(); + await this._captureVerticalFullPageMapSearch(); + await this._captureDirectAnswers(); + } + + async _captureUniversalSearch () { + await this._pageNavigator.gotoUniversalPage(); + await this._camera.snapshot('universal-search'); + + await this._pageNavigator.gotoUniversalPage({ query: 'a' }); + await this._camera.snapshot('universal-search--no-results'); + + await this._pageNavigator.gotoUniversalPage({ query: this._queries.faq }); + await this._pageNavigator.click('.HitchhikerFaqAccordion-toggle') + await this._camera.snapshot('universal-search--faq-accordion'); + + await this._pageNavigator.gotoUniversalPage({ query: 'yext answers'}); + await this._camera.snapshot('universal-search--product-prominentimage'); + } + + async _captureVerticalSearch () { + await this._pageNavigator.gotoVerticalPage('events'); + await this._camera.snapshot('vertical-search'); + + await this._pageNavigator.gotoVerticalPage('events', { query: 'a' }); + await this._camera.snapshot('vertical-search--no-results'); + + await this._pageNavigator.gotoVerticalPage('financial_professionals', { query: 'connor' }); + await this._camera.snapshot('vertical-search--financial-professional-location'); + + await this._pageNavigator.gotoVerticalPage('jobs', { query: this._queries.job }); + await this._camera.snapshot('vertical-search--job-standard'); + + await this._pageNavigator.gotoVerticalPage('help_articles', { query: 'slap chop' }); + await this._camera.snapshot('vertical-search--document-standard'); + + await this._pageNavigator.gotoVerticalPage('menu_items', { query: this._queries.menu_item }); + await this._camera.snapshot('vertical-search--menuitem-standard'); + } + + async _captureVerticalGridSearch () { + await this._pageNavigator.gotoVerticalPage('people', { query: 'a' }); + await this._camera.snapshot('vertical-grid-search'); + + await this._pageNavigator.gotoVerticalPage('people', { query: 'vrginia' }); + await this._camera.snapshot('vertical-grid-search--spellcheck'); + + await this._pageNavigator.gotoVerticalPage('products', { query: 'yext answers' }); + await this._camera.snapshot('vertical-grid-search--product-prominentvideo'); + + await this._pageNavigator.gotoVerticalPage('products_clickable_image', { query: 'yext answers' }); + await this._camera.snapshot('vertical-grid-search--product-prominentimage-clickable'); + } + + async _captureVerticalMapSearch () { + await this._pageNavigator.gotoVerticalPage('locations', { query: 'a' }); + await this._camera.snapshot('vertical-map-search'); + + await this._pageNavigator.gotoVerticalPage('locations_google', { query: 'virginia' }); + await this._camera.snapshot('vertical-map-search--google'); + } + + async _captureVerticalFullPageMapSearch () { + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: '' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map__desktop-view'); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-list-view'); + + await this._pageNavigator.click('.Answers-mobileToggle'); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-map-view'); + + const mapboxPinSelector = '.js-answersMap button'; + await this._pageNavigator.click(mapboxPinSelector); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-detail-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'office sparce'}); + await this._camera.snapshotDesktopOnly('vertical-full-page-map--spellcheck__desktop-view'); + await this._camera.snapshotMobileOnly('vertical-full-page-map--spellcheck__mobile-list-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'virginia' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map--nlp-filters__desktop-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map_with_filters', { query: 'virginia' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map-with-filters--nlp-filters__desktop-view'); + } + + async _captureDirectAnswers () { + await this._pageNavigator.gotoUniversalPage({ query: this._queries.field_direct_answers }); + await this._camera.snapshot('field-direct-answer'); + } +} + +module.exports = MultilangPhotographer; diff --git a/tests/percy/photographer.js b/tests/percy/photographer.js new file mode 100644 index 000000000..3ad306f20 --- /dev/null +++ b/tests/percy/photographer.js @@ -0,0 +1,143 @@ +/** + * @typedef {import('./pagenavigator.js')} PageNavigator + * @typedef {import('./Camera.js')} Camera + */ + +/** + * Responsible for determining which snapshots to take + */ +class Photographer { + /** + * @param {PageNavigator} pageNavigator + * @param {Camera} camera + */ + constructor(pageNavigator, camera) { + this._pageNavigator = pageNavigator; + this._camera = camera; + } + + async captureSnapshots() { + await this._captureUniversalSearch(); + await this._captureVerticalSearch(); + await this._captureVerticalGridSearch(); + await this._captureVerticalMapSearch(); + await this._captureVerticalFullPageMapSearch(); + await this._captureDirectAnswers(); + } + + async _captureUniversalSearch () { + await this._pageNavigator.gotoUniversalPage(); + await this._camera.snapshot('universal-search'); + + await this._pageNavigator.gotoUniversalPage({ query: 'a' }); + await this._camera.snapshot('universal-search--no-results'); + + await this._pageNavigator.gotoUniversalPage({ query: 'office sparce'}); + await this._camera.snapshot('universal-search--spellcheck'); + + await this._pageNavigator.gotoUniversalPage({ query: 'what if i forget my password?'}); + await this._pageNavigator.click('.HitchhikerFaqAccordion-toggle') + await this._camera.snapshot('universal-search--faq-accordion'); + + await this._pageNavigator.gotoUniversalPage({ query: 'yext answers'}); + await this._camera.snapshot('universal-search--product-prominentimage'); + } + + async _captureVerticalSearch () { + await this._pageNavigator.gotoVerticalPage('events'); + await this._camera.snapshot('vertical-search'); + + await this._pageNavigator.gotoVerticalPage('events', { query: 'a' }); + await this._camera.snapshot('vertical-search--no-results'); + + await this._pageNavigator.gotoVerticalPage('events', { query: 'vrginia' }); + await this._camera.snapshot('vertical-search--spellcheck'); + + await this._pageNavigator.gotoVerticalPage('events_custom_cta_icons'); + await this._camera.snapshot('vertical-search--custom-cta-icons'); + + await this._pageNavigator.gotoVerticalPage('financial_professionals', { query: 'connor' }); + await this._camera.snapshot('vertical-search--financial-professional-location'); + + await this._pageNavigator.gotoVerticalPage('healthcare_professionals', { query: 'bob' }); + await this._camera.snapshot('vertical-search--healthcare-professional-location'); + + await this._pageNavigator.gotoVerticalPage('jobs', { query: 'job' }); + await this._camera.snapshot('vertical-search--job-standard'); + + await this._pageNavigator.gotoVerticalPage('help_articles', { query: 'slap chop' }); + await this._camera.snapshot('vertical-search--document-standard'); + + await this._pageNavigator.gotoVerticalPage('menu_items', { query: 'roll' }); + await this._camera.snapshot('vertical-search--menuitem-standard'); + } + + async _captureVerticalGridSearch () { + await this._pageNavigator.gotoVerticalPage('people', { query: 'a' }); + await this._camera.snapshot('vertical-grid-search'); + + await this._pageNavigator.gotoVerticalPage('people', { query: 'vrginia' }); + await this._camera.snapshot('vertical-grid-search--spellcheck'); + + await this._pageNavigator.gotoVerticalPage('products', { query: 'yext answers' }); + await this._camera.snapshot('vertical-grid-search--product-prominentvideo'); + + await this._pageNavigator.gotoVerticalPage('products_clickable_image', { query: 'yext answers' }); + await this._camera.snapshot('vertical-grid-search--product-prominentimage-clickable'); + } + + async _captureVerticalMapSearch () { + await this._pageNavigator.gotoVerticalPage('locations', { query: 'a' }); + await this._camera.snapshot('vertical-map-search'); + + await this._pageNavigator.gotoVerticalPage('locations_google', { query: 'virginia' }); + await this._camera.snapshot('vertical-map-search--google'); + } + + async _captureVerticalFullPageMapSearch () { + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: '' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map__desktop-view'); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-list-view'); + + await this._pageNavigator.click('.Answers-mobileToggle'); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-map-view'); + + const mapboxPinSelector = '.js-answersMap button'; + await this._pageNavigator.click(mapboxPinSelector); + await this._camera.snapshotMobileOnly('vertical-full-page-map__mobile-detail-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map_with_filters', { query: 'people' }); + await this._camera.snapshot('vertical-full-page-map--alternative-verticals'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'office sparce'}); + await this._camera.snapshotDesktopOnly('vertical-full-page-map--spellcheck__desktop-view'); + await this._camera.snapshotMobileOnly('vertical-full-page-map--spellcheck__mobile-list-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'virginia' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map--nlp-filters__desktop-view'); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map_with_filters', { query: 'virginia' }); + await this._camera.snapshotDesktopOnly('vertical-full-page-map-with-filters--nlp-filters__desktop-view'); + } + + async _captureDirectAnswers () { + await this._pageNavigator.gotoUniversalPage({ query: 'bryan reed phone number' }); + await this._camera.snapshot('field-direct-answer'); + + await this._pageNavigator.gotoUniversalPage({ query: 'where was joe exotic born?' }); + await this._camera.snapshot('documentsearch-direct-answer') + + await this._pageNavigator.gotoUniversalPage({ query: 'how to get rich text' }); + await this._camera.snapshot('documentsearch-rich-text-direct-answer') + + await this._pageNavigator.gotoUniversalPage({ query: 'who is howard?' }); + await this._camera.snapshot('documentsearch-rich-text-picture-direct-answer') + } +} + +module.exports = Photographer; diff --git a/tests/browser-automation/multilangqueries.json b/tests/percy/queries.json similarity index 100% rename from tests/browser-automation/multilangqueries.json rename to tests/percy/queries.json diff --git a/tests/static/js/formatters-internal/generate-cta-field-type-link.js b/tests/static/js/formatters-internal/generate-cta-field-type-link.js index 2d7a753ac..3de5a33ab 100644 --- a/tests/static/js/formatters-internal/generate-cta-field-type-link.js +++ b/tests/static/js/formatters-internal/generate-cta-field-type-link.js @@ -25,11 +25,4 @@ describe('generateCtaFieldTypeLinks can handle translated link types', () => { } expect(generateCTAFieldTypeLink(cta)).toEqual('slap'); }); -}); - -it('works with no linkType set', () => { - const cta = { - link: 'slap' - } - expect(generateCTAFieldTypeLink(cta)).toEqual('slap'); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/tests/static/js/formatters-internal/highlightField.js b/tests/static/js/formatters-internal/highlightField.js deleted file mode 100644 index 2d7390808..000000000 --- a/tests/static/js/formatters-internal/highlightField.js +++ /dev/null @@ -1,39 +0,0 @@ -import Formatters from '../../../../static/js/formatters'; -const { highlightField } = Formatters; - -describe('highlightField properly handle snippets', () => { - it('snippet with empty matched substrings', () => { - const fieldValue = 'morbi tristique senectus et netus et malesuada fames ac turpis egestas.'; - const matchedSubstrings = []; - expect(highlightField(fieldValue, matchedSubstrings)).toEqual(fieldValue); - }); - - it('snippet with matched substrings at beginning of field value', () => { - const fieldValue = 'morbi tristique senectus et netus et malesuada fames ac turpis egestas.'; - const matchedSubstrings = [{ offset: 0, length: 5 }]; - - const expectedString = 'morbi tristique senectus et netus et malesuada fames ac turpis egestas.'; - expect(highlightField(fieldValue, matchedSubstrings)).toEqual(expectedString); - }); - - it('snippet with matched substrings at end of field value', () => { - const fieldValue = 'morbi tristique senectus et netus et malesuada fames ac turpis egestas.'; - const matchedSubstrings = [{ offset: 56, length: 15 }]; - - const expectedString = 'morbi tristique senectus et netus et malesuada fames ac turpis egestas.'; - expect(highlightField(fieldValue, matchedSubstrings)).toEqual(expectedString); - }); - - it('handle snippet with non-html brackets and multiple matched substrings', () => { - const fieldValue = '... script> some stuff 2 Joe Exotic was born Joseph Allen Schreibvogel in Garden City, ' - + 'Kansas, on March 5, 1963.[6][7][8], to parents Francis and Shirley Schreibvogel.[9] He grew up on a working farm ' - + 'in Kansas. He was Joseph Allen Schreibvogel in Garden City ...'; - const matchedSubstrings = [{ offset: 144, length: 32 }, { offset: 84, length: 19 }]; - - const expectedString = '... script> some stuff 2</script> Joe Exotic was born Joseph Allen Schreibvogel in' - + ' Garden City, Kansas, on March 5, 1963.[6][7][8], to parents Francis and Shirley Schreibvogel' - + '.[9] He grew up on a working farm in Kansas. <script> some ampersand stuff & & </script>' - + ' He was Joseph Allen Schreibvogel in Garden City ...'; - expect(highlightField(fieldValue, matchedSubstrings)).toEqual(expectedString); - }); -}); \ No newline at end of file diff --git a/tests/static/js/formatters-internal/image.js b/tests/static/js/formatters-internal/image.js index c714334d9..01996bbb1 100644 --- a/tests/static/js/formatters-internal/image.js +++ b/tests/static/js/formatters-internal/image.js @@ -2,55 +2,99 @@ import Formatters from 'static/js/formatters.js'; describe('image formatter', () => { const img = { - url: 'https://a.mktgcdn.com/p/1024x768.jpg' + url: 'https://a.mktgcdn.com/p/1024x768.jpg', + width: 1024, + height: 768, + thumbnails: [ + { + url: 'https://a.mktgcdn.com/p/619x348.jpg', + width: 619, + height: 348 + }, + { + url: 'https://a.mktgcdn.com/p/600x337.jpg', + width: 600, + height: 337 + }, + { + url: 'https://a.mktgcdn.com/p/196x110.jpg', + width: 196, + height: 110 + } + ] } describe('when choosing the smallest image over threshold', () => { it('By default chooses the smallest image with width >= 200', () => { const imageUrl = Formatters.image(img).url; - expect(imageUrl).toEqual('https://dynl.mktgcdn.com/p/200x1.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/600x337.jpg'); }); it('Can restrict the dimensions by width', () => { const imageUrl = Formatters.image(img, '601x').url; - expect(imageUrl).toEqual('https://dynl.mktgcdn.com/p/601x1.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/619x348.jpg'); + }); + + it('Can restrict by width when both dimensions specified', () => { + const imageUrl = Formatters.image(img, '601x1').url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/619x348.jpg'); }); it('Can restrict the dimensions by height', () => { const imageUrl = Formatters.image(img, 'x338').url; - expect(imageUrl).toEqual('https://dynl.mktgcdn.com/p/1x338.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/619x348.jpg'); + }); + + it('Can restrict by height when both dimensions specified', () => { + const imageUrl = Formatters.image(img, '1x338').url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/619x348.jpg'); + }); + + it('Can restrict by width when both dimensions specified', () => { + const imageUrl = Formatters.image(img, '601x0').url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/619x348.jpg'); }); - it('Can restrict by both dimensions', () => { - const imageUrl = Formatters.image(img, '601x338').url; - expect(imageUrl).toEqual('https://dynl.mktgcdn.com/p/601x338.jpg'); + it('return the largest image when no image is over threshold', () => { + const imageUrl = Formatters.image(img, '99999x99999').url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/1024x768.jpg'); }); it('returns the smallest image when no dimensions given', () => { const imageUrl = Formatters.image(img, 'x').url; - expect(imageUrl).toEqual('https://dynl.mktgcdn.com/p/1x1.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/196x110.jpg'); }); }); describe('when choosing the biggest image under threshold', () => { it('Can restrict the dimensions by width', () => { const imageUrl = Formatters.image(img, '601x', false).url; - expect(imageUrl).toEqual('https://dynm.mktgcdn.com/p/601x768.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/600x337.jpg'); + }); + + it('Can restrict by width when both dimensions specified', () => { + const imageUrl = Formatters.image(img, '601x9999', false).url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/600x337.jpg'); }); it('Can restrict the dimensions by height', () => { const imageUrl = Formatters.image(img, 'x338', false).url; - expect(imageUrl).toEqual('https://dynm.mktgcdn.com/p/1024x338.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/600x337.jpg'); + }); + + it('Can restrict by height when both dimensions specified', () => { + const imageUrl = Formatters.image(img, '9999x338', false).url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/600x337.jpg'); }); - it('Can restrict by both dimensions', () => { - const imageUrl = Formatters.image(img, '999x338', false).url; - expect(imageUrl).toEqual('https://dynm.mktgcdn.com/p/999x338.jpg'); + it('returns the smallest image when no image is under threshold', () => { + const imageUrl = Formatters.image(img, '-1x-1', false).url; + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/196x110.jpg'); }); it('return the largest image when no dimensions given', () => { const imageUrl = Formatters.image(img, 'x', false).url; - expect(imageUrl).toEqual('https://dynm.mktgcdn.com/p/1024x768.jpg'); + expect(imageUrl).toEqual('https://a.mktgcdn.com/p/1024x768.jpg'); }); }); }); \ No newline at end of file diff --git a/tests/templates/script/fixtures/directanswer.hbs.js b/tests/templates/script/fixtures/directanswer.hbs.js deleted file mode 100644 index 26566ae1a..000000000 --- a/tests/templates/script/fixtures/directanswer.hbs.js +++ /dev/null @@ -1,2 +0,0 @@ -ANSWERS.addComponent("DirectAnswer", -{"container":"#js-answersDirectAnswer"}); diff --git a/tests/wcag/index.js b/tests/wcag/index.js index 12be4986f..16d4ea0cf 100755 --- a/tests/wcag/index.js +++ b/tests/wcag/index.js @@ -3,9 +3,8 @@ const HttpServer = require('../test-utils/server'); const { AxePuppeteer } = require('@axe-core/puppeteer'); const StandardPageNavigator = require('../percy/standardpagenavigator'); +const WcagReporter = require('./wcagreporter'); const puppeteer = require('puppeteer'); -const PageOperator = require('../browser-automation/pageoperator'); -const getTestingLocations = require('../browser-automation/testlocations'); const PORT = 5042; /** @@ -34,15 +33,11 @@ async function wcagTester() { const page = await browser.newPage(); const standardPageNavigator = new StandardPageNavigator(page, `http://localhost:${PORT}`); - const analyzer = new AxePuppeteer(page).options(config); + const analyzer = await new AxePuppeteer(page).options(config); let results = []; try { - const operator = new PageOperator(standardPageNavigator, page, getTestingLocations()); - while (operator.hasNextTestLocation()) { - await operator.nextTestLocation(); - results.push(await analyzer.analyze()); - } + results = await new WcagReporter(standardPageNavigator, analyzer, page).analyze(); } catch (e) { console.log(e); await browser.close(); diff --git a/tests/wcag/wcagreporter.js b/tests/wcag/wcagreporter.js new file mode 100644 index 000000000..44d7144b5 --- /dev/null +++ b/tests/wcag/wcagreporter.js @@ -0,0 +1,147 @@ +const { BrowserPageWidths } = require("../percy/constants"); + +class WcagReporter { + /** + * @param {PageNavigator} pageNavigator + * @param {import('@axe-core/puppeteer')} analyzer + * @param {import('puppeteer').Page} page + */ + constructor (pageNavigator, analyzer, page) { + this._pageNavigator = pageNavigator; + this._analyzer = analyzer; + this._page = page; + this.results = []; + } + + async analyze() { + await this._analyzeUniversalSearch(); + await this._analyzeVerticalSearch(); + await this._analyzeVerticalGridSearch(); + await this._analyzeVerticalMapSearch(); + await this._analyzeVerticalFullPageMapSearch(); + await this._analyzeDirectAnswers(); + return this.results; + } + + + async _analyzeUniversalSearch() { + await this._pageNavigator.gotoUniversalPage(); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'a' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'office sparce'}); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'what if i forget my password?'}); + await this._pageNavigator.click('.HitchhikerFaqAccordion-toggle') + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'yext answers'}); + this.results.push(await this._analyzer.analyze()); + + } + + async _analyzeVerticalSearch() { + await this._pageNavigator.gotoVerticalPage('events'); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('events', { query: 'a' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('events', { query: 'vrginia' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('events_custom_cta_icons'); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('financial_professionals', { query: 'connor' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('healthcare_professionals', { query: 'bob' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('jobs', { query: 'job' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('help_articles', { query: 'slap chop' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('menu_items', { query: 'roll' }); + this.results.push(await this._analyzer.analyze()); + } + + async _analyzeVerticalGridSearch () { + await this._pageNavigator.gotoVerticalPage('people', { query: 'a' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('people', { query: 'vrginia' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('products', { query: 'yext answers' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('products_clickable_image', { query: 'yext answers' }); + this.results.push(await this._analyzer.analyze()); + } + + async _analyzeVerticalMapSearch () { + await this._pageNavigator.gotoVerticalPage('locations', { query: 'a' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoVerticalPage('locations_google', { query: 'virginia' }); + this.results.push(await this._analyzer.analyze()); + } + + async _analyzeVerticalFullPageMapSearch () { + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: '' }); + this.results.push(await this._analyzer.analyze()); + + await this._page.setViewport({ width: BrowserPageWidths.Mobile, height: this._page.viewport().height }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.click('.Answers-mobileToggle'); + this.results.push(await this._analyzer.analyze()); + + const mapboxPinSelector = '.js-answersMap button'; + await this._pageNavigator.click(mapboxPinSelector); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'office sparce'}); + this.results.push(await this._analyzer.analyze()); + + await this._page.setViewport({ width: BrowserPageWidths.Desktop, height: this._page.viewport().height }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map', { query: 'virginia' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map_with_filters', { query: 'people' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator + .gotoVerticalPage('locations_full_page_map_with_filters', { query: 'virginia' }); + this.results.push(await this._analyzer.analyze()); + } + + async _analyzeDirectAnswers () { + await this._pageNavigator.gotoUniversalPage({ query: 'bryan reed phone number' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'where was joe exotic born?' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'how to get rich text' }); + this.results.push(await this._analyzer.analyze()); + + await this._pageNavigator.gotoUniversalPage({ query: 'who is howard?' }); + this.results.push(await this._analyzer.analyze()); + } +} + +module.exports = WcagReporter;