From 5b45f9c23dd32bfee5b258b4a49a48e8bceff401 Mon Sep 17 00:00:00 2001 From: Elan Bartholomew Date: Fri, 10 May 2024 07:27:20 -0600 Subject: [PATCH 01/14] add support for custom endpoint --- libs/blocks/form/form.js | 9 +++++---- test/blocks/form/mocks/body.html | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/blocks/form/form.js b/libs/blocks/form/form.js index d6739877ba..d6fb180147 100644 --- a/libs/blocks/form/form.js +++ b/libs/blocks/form/form.js @@ -232,7 +232,7 @@ function lowercaseKeys(obj) { }, {}); } -async function createForm(formURL, thankYou, formData) { +async function createForm(formURL, thankYou, formData, endpoint = '') { const { pathname } = new URL(formURL); let json = formData; /* c8 ignore next 4 */ @@ -243,7 +243,7 @@ async function createForm(formURL, thankYou, formData) { json.data = json.data.map((obj) => lowercaseKeys(obj)); const form = createTag('form'); const rules = []; - const [action] = pathname.split('.json'); + const [action] = endpoint ? [endpoint] : pathname.split('.json'); form.dataset.action = action; const typeToElement = { @@ -290,8 +290,9 @@ async function createForm(formURL, thankYou, formData) { } export default async function decorate(block, formData = null) { - const form = block.querySelector('a[href$=".json"]'); + const [form, endpoint] = block.querySelectorAll(':scope > div:first-child a'); const thankYou = block.querySelector(':scope > div:last-of-type > div'); thankYou.remove(); - if (form) form.replaceWith(await createForm(form.href, thankYou, formData)); + if (endpoint) endpoint.parentElement.remove(); + if (form) form.replaceWith(await createForm(form.href, thankYou, formData, endpoint?.href)); } diff --git a/test/blocks/form/mocks/body.html b/test/blocks/form/mocks/body.html index cf586758ec..f0414b692a 100644 --- a/test/blocks/form/mocks/body.html +++ b/test/blocks/form/mocks/body.html @@ -1,6 +1,7 @@
https://main--milo--adobecom.hlx.page/drafts/ebartholomew/forms/test-form.json
+
https://main--milo--adobecom.hlx.page/drafts/ebartholomew/forms/test-form
Thank you
From eea752eedf1cb64552362479eeed8abbc98334b6 Mon Sep 17 00:00:00 2001 From: Elan Bartholomew Date: Tue, 14 May 2024 10:56:46 -0600 Subject: [PATCH 02/14] update tests --- test/blocks/form/form.test.js | 6 +----- test/blocks/form/mocks/form-data.json | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/blocks/form/form.test.js b/test/blocks/form/form.test.js index 5ce5050e16..8a2318450b 100644 --- a/test/blocks/form/form.test.js +++ b/test/blocks/form/form.test.js @@ -92,11 +92,7 @@ describe('Form Block', async () => { it('submits successfully', async () => { const form = await waitForElement('form'); - const reqCheck = form.querySelector('.group-container.required input'); - const submit = form.querySelector('.form-submit-wrapper button'); - reqCheck.checked = true; - reqCheck.closest('.field-wrapper').dispatchEvent(new Event('input')); - submit.dispatchEvent(new Event('click')); + form.querySelector('.form-submit-wrapper button').dispatchEvent(new Event('click')); await new Promise((resolve) => { setTimeout(() => resolve(), 150); }); const thanks = document.querySelector('.thank-you'); expect(thanks).to.exist; diff --git a/test/blocks/form/mocks/form-data.json b/test/blocks/form/mocks/form-data.json index 67f0ece524..54a2a020f9 100644 --- a/test/blocks/form/mocks/form-data.json +++ b/test/blocks/form/mocks/form-data.json @@ -1 +1 @@ -{"total":23,"offset":0,"limit":23,"data":[{"Field":"legal","Label":"This is legal text","Placeholder":"","Type":"legal","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"title","Label":"This is a Heading","Placeholder":"","Type":"heading","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"firstName","Label":"First Name:","Placeholder":"First Name","Type":"","Required":"x","Options":"","Rules":"","Default":"","Extra":""},{"Field":"lastName","Label":"Last Name:","Placeholder":"Last Name","Type":"","Required":"x","Options":"","Rules":"","Default":"","Extra":""},{"Field":"email","Label":"Email:","Placeholder":"Email","Type":"email","Required":"x","Options":"","Rules":"","Default":"","Extra":""},{"Field":"favoriteNumber","Label":"What is your favorite number?","Placeholder":"","Type":"number","Required":"x","Options":"","Rules":"","Default":"","Extra":""},{"Field":"favoriteColor","Label":"What is your favorite color?","Placeholder":"Select One","Type":"select","Required":"x","Options":"Purple, Green, Red, Other","Rules":"","Default":"Red","Extra":""},{"Field":"coffeeTea","Label":"Do you prefer coffee or tea?","Placeholder":"","Type":"radio-group","Required":"","Options":"Coffee, Tea","Rules":"","Default":"Coffee","Extra":""},{"Field":"birthday","Label":"Please enter your birthday","Placeholder":"","Type":"date","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"agree","Label":"Do you agree?","Placeholder":"","Type":"checkbox","Required":"x","Options":"Yes","Rules":"","Default":"","Extra":""},{"Field":"genres","Label":"What genres of music do you like? (Check all that apply)","Placeholder":"","Type":"checkbox-group","Required":"","Options":"Hip-Hop, Rock, Alternative, Country, Dance, Pop","Rules":"","Default":"Hip-Hop, Alternative, Dance","Extra":""},{"Field":"tellUs","Label":"Tell us what you think!","Placeholder":"","Type":"text-area","Required":"x","Options":"","Rules":"","Default":"","Extra":""},{"Field":"hiddenFieldEq","Label":"This should be hidden if the number is equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldNe","Label":"This should be hidden if the number is not equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"!=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldGt","Label":"This should be hidden if the number is greater than 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \">\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldGe","Label":"This should be hidden if the number is greater than or equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \">=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldLt","Label":"This should be hidden if the number is less than 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"<\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldLe","Label":"This should be hidden if the number is less than or equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"<=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldInc","Label":"This should be hidden if \"Pop\" is checked","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"genres\", \"operator\": \"inc\", \"value\": \"Pop\"}}","Default":"","Extra":""},{"Field":"hiddenFieldExc","Label":"This should be hidden if \"Pop\" is NOT checked","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"genres\", \"operator\": \"exc\", \"value\": \"Pop\"}}","Default":"","Extra":""},{"Field":"hiddenField","Label":"This should always be visible because the rule contains an invalid operator","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"foo\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"submit","Label":"Submit","Placeholder":"","Type":"submit","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"clear","Label":"Clear","Placeholder":"","Type":"clear","Required":"","Options":"","Rules":"","Default":"","Extra":""}],":type":"sheet"} +{"total":23,"offset":0,"limit":23,"data":[{"Field":"legal","Label":"This is legal text","Placeholder":"","Type":"legal","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"title","Label":"This is a Heading","Placeholder":"","Type":"heading","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"firstName","Label":"First Name:","Placeholder":"First Name","Type":"","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"lastName","Label":"Last Name:","Placeholder":"Last Name","Type":"","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"email","Label":"Email:","Placeholder":"Email","Type":"email","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"favoriteNumber","Label":"What is your favorite number?","Placeholder":"","Type":"number","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"favoriteColor","Label":"What is your favorite color?","Placeholder":"Select One","Type":"select","Required":"","Options":"Purple, Green, Red, Other","Rules":"","Default":"Red","Extra":""},{"Field":"coffeeTea","Label":"Do you prefer coffee or tea?","Placeholder":"","Type":"radio-group","Required":"","Options":"Coffee, Tea","Rules":"","Default":"Coffee","Extra":""},{"Field":"birthday","Label":"Please enter your birthday","Placeholder":"","Type":"date","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"agree","Label":"Do you agree?","Placeholder":"","Type":"checkbox","Required":"","Options":"Yes","Rules":"","Default":"","Extra":""},{"Field":"genres","Label":"What genres of music do you like? (Check all that apply)","Placeholder":"","Type":"checkbox-group","Required":"","Options":"Hip-Hop, Rock, Alternative, Country, Dance, Pop","Rules":"","Default":"Hip-Hop, Alternative, Dance","Extra":""},{"Field":"tellUs","Label":"Tell us what you think!","Placeholder":"","Type":"text-area","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"hiddenFieldEq","Label":"This should be hidden if the number is equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldNe","Label":"This should be hidden if the number is not equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"!=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldGt","Label":"This should be hidden if the number is greater than 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \">\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldGe","Label":"This should be hidden if the number is greater than or equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \">=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldLt","Label":"This should be hidden if the number is less than 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"<\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldLe","Label":"This should be hidden if the number is less than or equal to 10","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"<=\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"hiddenFieldInc","Label":"This should be hidden if \"Pop\" is checked","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"genres\", \"operator\": \"inc\", \"value\": \"Pop\"}}","Default":"","Extra":""},{"Field":"hiddenFieldExc","Label":"This should be hidden if \"Pop\" is NOT checked","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"genres\", \"operator\": \"exc\", \"value\": \"Pop\"}}","Default":"","Extra":""},{"Field":"hiddenField","Label":"This should always be visible because the rule contains an invalid operator","Placeholder":"","Type":"","Required":"","Options":"","Rules":"{\"type\": \"hidden\", \"condition\": {\"key\": \"favoriteNumber\", \"operator\": \"foo\", \"value\": \"10\"}}","Default":"","Extra":""},{"Field":"submit","Label":"Submit","Placeholder":"","Type":"submit","Required":"","Options":"","Rules":"","Default":"","Extra":""},{"Field":"clear","Label":"Clear","Placeholder":"","Type":"clear","Required":"","Options":"","Rules":"","Default":"","Extra":""}],":type":"sheet"} From 80515d935f311d16dd509ed570a1d628159cf321 Mon Sep 17 00:00:00 2001 From: Sanjay Rai Date: Mon, 13 May 2024 22:59:19 -0700 Subject: [PATCH 03/14] MWPW-147599: CaaS Bulk Publisher not working after MS authentication change (#2248) Potential fix for bulk publisher issues Co-authored-by: Blaine Gunn Co-authored-by: Sheridan Sunier --- tools/send-to-caas/bulk-publish-to-caas.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/send-to-caas/bulk-publish-to-caas.js b/tools/send-to-caas/bulk-publish-to-caas.js index 51390ea1fe..ab00fdd894 100644 --- a/tools/send-to-caas/bulk-publish-to-caas.js +++ b/tools/send-to-caas/bulk-publish-to-caas.js @@ -115,9 +115,7 @@ const processData = async (data, accessToken) => { let domain = `https://${host}`; - if (usePreview) { - domain = `https://main--${repo}--${owner}.hlx.page`; - } else if (publishToFloodgate !== 'default') { + if (usePreview || publishToFloodgate !== 'default') { domain = `https://main--${repo}--${owner}.hlx.live`; } From 2efcb3346376d89d29ef9dc224a04aedc9040f27 Mon Sep 17 00:00:00 2001 From: Ryan Clayton Date: Tue, 14 May 2024 00:00:12 -0600 Subject: [PATCH 04/14] Preflight Accessibility tab update (#2254) Updating how alt text is used and displayed in preflight Co-authored-by: Ryan Clayton --- libs/blocks/preflight/panels/accessibility.js | 138 ++++++++++++++---- libs/blocks/preflight/preflight.css | 122 +++++++++++++--- 2 files changed, 211 insertions(+), 49 deletions(-) diff --git a/libs/blocks/preflight/panels/accessibility.js b/libs/blocks/preflight/panels/accessibility.js index acaa9857c8..2959515e6a 100644 --- a/libs/blocks/preflight/panels/accessibility.js +++ b/libs/blocks/preflight/panels/accessibility.js @@ -1,58 +1,132 @@ import { html, signal, useEffect } from '../../../deps/htm-preact.js'; -const DEF_ICON = 'purple'; const DEF_DESC = 'Checking...'; -const pass = 'green'; -const fail = 'red'; +const decorativeImages = signal([]); +const altTextImages = signal([]); +const altResult = signal({ title: 'Image alt value', description: DEF_DESC }); +const groups = [ + { title: 'Images with alt text', imgArray: altTextImages }, + { title: 'Decorative images (empty alt text)', imgArray: decorativeImages, closed: true }, +]; +const filterOptions = [ + { value: '', content: 'All' }, + { value: 'show-main', content: 'Main content', selected: true }, + { value: 'show-gnav', content: 'Gnav' }, + { value: 'show-footer', content: 'Footer' }, +]; -const content = signal({}); -const altResult = signal({ icon: DEF_ICON, title: 'Image alt value', description: DEF_DESC }); +function filterGrid(e) { + const imgGrid = e.target.parentElement.parentElement; + filterOptions.forEach((option) => { + if (imgGrid.classList.contains(option.value)) { + imgGrid.classList.remove(option.value); + } + }); + if (e.target.value) imgGrid.classList.add(e.target.value); +} + +function toggleGrid(e) { + e.preventDefault(); + const clickArea = e.target.nodeName === 'SPAN' ? e.target.parentElement.parentElement : e.target.parentElement; + clickArea.classList.toggle('is-closed'); +} + +function dropdownOptions(props) { + const selected = props.option.selected === true; + return html` + + `; +} async function checkAlt() { - const main = document.querySelector('main'); - const images = main.querySelectorAll('img'); + if (altResult.value.checked) return; + // If images are not scoped, tracking pixel/images are picked up. + const images = document.querySelectorAll('header img, main img, footer img'); const result = { ...altResult.value }; - const imagesWithoutAlt = []; + if (!images) return; + images.forEach((img) => { const alt = img.getAttribute('alt'); - if (!alt || alt.trim() === '') { - imagesWithoutAlt.push(img.getAttribute('src')); + let parent = ''; + + if (img.closest('header')) parent = 'gnav'; + if (img.closest('main')) parent = 'main-content'; + if (img.closest('footer')) parent = 'footer'; + if (alt === '') { + img.dataset.altCheck = 'decorative'; + decorativeImages.value = [...decorativeImages.value, + { + src: img.getAttribute('src'), + altCheck: img.dataset.altCheck, + parent, + }]; + } + if (alt) { + altTextImages.value = [...altTextImages.value, + { + src: img.getAttribute('src'), + alt, + parent, + }]; } + img.dataset.pageLocation = parent; }); - if (!imagesWithoutAlt.length) { - result.icon = pass; - result.description = 'Reason: All images are valid'; - } else { - result.icon = fail; - result.description = 'Reason: Alt text missing for the following images:'; - } - content.value = imagesWithoutAlt; - altResult.value = result; + result.description = 'All images listed below. Please validate each alt text has been set appropriately. Decorative images have been highlighted in yellow on the page.'; + altResult.value = { ...result, checked: true }; } -function AccessibilityItem({ icon, title, description }) { +function AccessibilityItem({ title, description }) { return html`
-
-
-

${title}

-

${description}

+
+

${title}

+

${description}

`; } +function ImageGroups({ group }) { + const setFilterView = filterOptions.find((option) => option.selected === true); + const { imgArray, closed } = group; + return html` + + + ${imgArray.value.length > 0 && html` +
+
+ Filter images by: + +
+ + ${imgArray.value.map((img) => html` +
+ + ${!img.altCheck ? `Alt=${img.alt}` : `Marked as ${img.altCheck}`} + Located in ${img.parent} +
`)} +
`} + + ${!imgArray.value.length && html` +
+
No images found
+
+ `} + `; +} + export default function Accessibility() { useEffect(() => { checkAlt(); }, []); return html`
- <${AccessibilityItem} icon=${altResult.value.icon} title=${altResult.value.title} description=${altResult.value.description} /> - ${content.value.length > 0 && html` -

Images

-
- ${Object.keys(content.value).map((key) => html`
-
`)} -
- `} + <${AccessibilityItem} title=${altResult.value.title} description=${altResult.value.description} /> + ${groups.map((group) => html`<${ImageGroups} group=${group} />`)}
`; } diff --git a/libs/blocks/preflight/preflight.css b/libs/blocks/preflight/preflight.css index e730140aab..40210aa579 100644 --- a/libs/blocks/preflight/preflight.css +++ b/libs/blocks/preflight/preflight.css @@ -1,5 +1,6 @@ :root { --notch-size: 12px; + --action-color: #FF1593; } #preflight .fragment, @@ -237,7 +238,7 @@ span.preflight-time { } .preflight-action { - background: #FF1593; + background: var(--action-color); color: #FFF; font-weight: 700; outline: transparent solid 0; @@ -420,39 +421,126 @@ span.preflight-time { gap: 48px; } +.access-columns .grid-heading { + margin-bottom: 20px; +} + +.access-columns .grid-heading + .access-columns .grid-heading { + margin-top: 20px; +} + +.access-columns .grid-heading.is-closed { + transform: none; +} + +.access-columns .grid-toggle { + color: #fff; + font-weight: 700; + text-transform: uppercase; + display: grid; + grid-template-columns: 42px 1fr; + align-items: center; +} + .access-item { display: grid; grid-template-columns: auto 1fr; gap: 12px; } +.access-item-title { + margin: 0; + font-weight: 700; + font-size: 32px; + line-height: 1; +} + +.access-item-description { + margin: 10px 0 48px; +} + .access-image-grid { display: grid; - grid-template-columns: repeat(5, 1fr); - grid-gap: 20px; - max-width: 100%; - margin: 20px; - margin-left: 72px; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + grid-gap: 10px; + margin-bottom: 35px; + width: 100%; +} + +.access-image-grid:last-child { + margin-bottom: 0; +} + +.access-columns .grid-heading.is-closed + .access-image-grid { + display: none; } .access-image-grid-item { - border: solid white 4px; position: relative; - overflow: hidden; - width: 128px; - height: 128px; + height: auto; + background: rgb(0 0 0 / 20%); + display: flex; + flex-flow: column; + align-items: center; + padding: 10px; + border-radius: 6px; + box-sizing: border-box; } -.access-image-grid-item img { +.access-image-grid-item.full-width { width: 100%; - height: 100%; - object-fit: cover; + max-width: initial; } -.access-image-header { - text-transform: uppercase; - font-weight: 700; - margin-left: 72px; +.access-image-grid .filter { + grid-column: 1 / 5; + align-items: start; + background: none; + display: block; + font-size: 16px; +} + +img[data-alt-check] { + border: 5px solid rgb(255 234 2); + box-sizing: border-box; + filter: drop-shadow(8px 8px 18px rgb(199 182 2)); +} + +img[data-alt-check]::after { + content: attr(data-alt-check); + color: red; +} + +.access-image-grid-item span { + font-size: 16px; + font-weight: bold; + margin-top: 10px; + line-height: 1.3rem; +} + +.access-image-grid-item span:last-child { + font-weight: initial; + opacity: 0.8; + margin-top: 0; +} + +.show-main .access-image-grid-item.in-gnav, +.show-main .access-image-grid-item.in-footer, +.show-gnav .access-image-grid-item.in-main-content, +.show-gnav .access-image-grid-item.in-footer, +.show-footer .access-image-grid-item.in-main-content, +.show-footer .access-image-grid-item.in-gnav { + display: none; +} + +.preflight .image-filter { + padding: 3px; + margin-left: 5px; + border-radius: 4px; +} + +.preflight .image-filter:focus-visible { + outline-color: var(--action-color); } .preflight .martech { From c755c30146c308fddc4b39212586c02ae212b363 Mon Sep 17 00:00:00 2001 From: Sheridan Sunier Date: Tue, 14 May 2024 01:27:28 -0700 Subject: [PATCH 05/14] MWPW-146407: add new card style to caas configurator (#2279) Co-authored-by: Brad Johnson Co-authored-by: Sheridan Sunier --- libs/blocks/caas-config/caas-config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/blocks/caas-config/caas-config.js b/libs/blocks/caas-config/caas-config.js index 738bc11319..f76fff9e9c 100644 --- a/libs/blocks/caas-config/caas-config.js +++ b/libs/blocks/caas-config/caas-config.js @@ -75,6 +75,7 @@ const defaultOptions = { 'double-wide': 'Double Width Card', product: 'Product Card', 'text-card': 'Text Card', + 'icon-card': 'Icon Card', 'custom-card': 'Custom Card', }, collectionBtnStyle: { From cde37b5e185e233d6a3993536642e5619aa55977 Mon Sep 17 00:00:00 2001 From: Elan Bartholomew <79870969+elan-tbx@users.noreply.github.com> Date: Tue, 14 May 2024 04:04:05 -0600 Subject: [PATCH 06/14] MWPW-141780 - Clean up Accordion block attributes (#2276) remove role attribute on dd elements Co-authored-by: Okan Sahin <39759830+mokimo@users.noreply.github.com> --- libs/blocks/accordion/accordion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/blocks/accordion/accordion.js b/libs/blocks/accordion/accordion.js index 5700630ad9..f67abbcbc6 100644 --- a/libs/blocks/accordion/accordion.js +++ b/libs/blocks/accordion/accordion.js @@ -92,7 +92,7 @@ function createItem(accordion, id, heading, num, edit) { const dtAttrs = hTag ? {} : { role: 'heading', 'aria-level': 3 }; const dtHtml = hTag ? createTag(hTag.tagName, { class: 'accordion-heading' }, button) : button; const dt = createTag('dt', dtAttrs, dtHtml); - const dd = createTag('dd', { role: 'region', 'aria-labelledby': triggerId, id: panelId, hidden: true }, panel); + const dd = createTag('dd', { 'aria-labelledby': triggerId, id: panelId, hidden: true }, panel); const dm = createTag('div', { class: 'media-p' }); if (edit) { From c4a1f4a60de8bee972fa291f2c8c0c90c29768e0 Mon Sep 17 00:00:00 2001 From: cmiqueo <64917520+cmiqueo@users.noreply.github.com> Date: Tue, 14 May 2024 03:06:14 -0700 Subject: [PATCH 07/14] MWPW-147158: adds support for footer divider at the collection level (#2198) * MWPW-147158: adds support for footer divider at the collection level * Updatest unit-test files * Update windows copy hash * Update OSX copy hash * Updates OSX hash again * Removes console log * Adds console logs for debbuging * Removes console logs * Adds console logs for debbuging again * Removes console log * Updates OSX hash * Adds debuging message to test * Update os-hash check logic * trim() generated hash * Changes the comparison logic for the hash * Reverts last attempt * new attempt to fix test --------- Co-authored-by: Okan Sahin <39759830+mokimo@users.noreply.github.com> --- libs/blocks/caas-config/caas-config.js | 1 + libs/blocks/caas/utils.js | 2 ++ test/blocks/caas-config/caas-config.test.html | 12 +++++------- .../caas-config/expectedConfigs/defaultConfig.js | 1 + test/blocks/caas/utils.test.js | 3 +++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libs/blocks/caas-config/caas-config.js b/libs/blocks/caas-config/caas-config.js index f76fff9e9c..2efac32ab6 100644 --- a/libs/blocks/caas-config/caas-config.js +++ b/libs/blocks/caas-config/caas-config.js @@ -350,6 +350,7 @@ const BasicsPanel = ({ tagsData }) => { const UiPanel = () => html` <${Input} label="Show Card Borders" prop="setCardBorders" type="checkbox" /> + <${Input} label="Show Footer Dividers" prop="showFooterDivider" type="checkbox" /> <${Input} label="Disable Card Banners" prop="disableBanners" type="checkbox" /> <${Input} label="Use Light Text" prop="useLightText" type="checkbox" /> <${Input} label="Use Overlay Links" prop="useOverlayLinks" type="checkbox" /> diff --git a/libs/blocks/caas/utils.js b/libs/blocks/caas/utils.js index db532b7328..6b6a885e84 100644 --- a/libs/blocks/caas/utils.js +++ b/libs/blocks/caas/utils.js @@ -576,6 +576,7 @@ export const getConfig = async (originalState, strs = {}) => { }, detailsTextOption: state.detailsTextOption, setCardBorders: state.setCardBorders, + showFooterDivider: state.showFooterDivider, useOverlayLinks: state.useOverlayLinks, collectionButtonStyle: state.collectionBtnStyle, banner: { @@ -793,6 +794,7 @@ export const defaultState = { secondaryTags: [], secondarySource: [], setCardBorders: false, + showFooterDivider: false, showBookmarksFilter: false, showBookmarksOnCards: false, showFilters: false, diff --git a/test/blocks/caas-config/caas-config.test.html b/test/blocks/caas-config/caas-config.test.html index b88f21189a..ee7013751a 100644 --- a/test/blocks/caas-config/caas-config.test.html +++ b/test/blocks/caas-config/caas-config.test.html @@ -316,14 +316,12 @@ // This does not affect the decoded hash value, // so either of these are valid hashes for the same content - const windowsHash = '~~H4sIAAAAAAAAA3VVTY/bNhD9LzwrWafb9qDb2ruLGPBm3diLHoqgGJMjiTDFUcmhvUrR/15Q31Kcm/jecIbz5kP/ClBKsyYL5iv+E9DzHhyUXqR/fUsEWDA1a+k3ZAzKaPcFShSpEBPy6ECet2Xl0HtNVqQZGI/RQO0o1/IIee8vMG0oWHb1Dmw+WJ6IziW481aSPWCM1IaY4m/WTxgJTh24NvEtBZjsQ4E6L7hjjpoNPkgZH3TSRnO9wwsakf6eCDmksmbbu6icLsHVYkqPmY5Y43gJHvT3AbMM2qITqfj0y2r1Au9/asVFR6HlY13hqIdstRCpkAA+7Y53wccLwTOVG3Cq883w0IQTqfjbo8lEIhR9Id7B93pHoAY1lfZwMrgGa9H5EXaQ8eNpOKNVFWkbBb1erx9B0Qk/SirvZKFLdPABKn03ZinijYt2ZEu0XRXwXZqgUMVXdil10JhjBsacQJ6fxnAiERkCBze7mWnD6J4ug/cWWAdt1B5sLF/TQCWwlgO9IwmdKgYznuC5liIV5AZoFsdvGn1n0KGg61NZcT1olAfmppq/votEFAhqcFNohRuGrZqfx8S1XShhwOYBcuzL3Z/vMIproKbQ9EcMF6oIEagXcnizUS3xYrrImjqmsO6mZlC3S4bc4kIFubaNeg9Wl83HEAdyVGJq8mRjU41dNjJ/BLCsuYltb/BdTh3QFGQk3zweCyzxfrxoQGJBRqF7c6ZtBYc+GPZ7dPtGwN8S4RGcLJ41mr4CHiVZBa4eMxygAwUnsQc5CrMmp6bz4SfS+eemI25zr3auaySf+w6bYNuFzaF58Qw6EsfF2yQ3EuT4ERgfvPwBe8Qb4AspnelJbRoCMwgmjpLq77VEW8g9VaGaXWjxr2AVlQcoK6MnG7oxiKN5IMcz9Lmb5BnYv2iZQo//kEYbdg6hR3ch7fZERqSfVqvVgmheiSK9b/F26y8cN+AiXNcKooDr2YtviWDIfdtrP9+E0UZEU5cjx0180XFRiAFbDgjHto5rKf6Y0MfVpJBBG3/Ed36tuq2lujolguNTPyMobfPufyWK+0jELml67khxyKIYiQged9F19DYEDR5fL+gM1Dttz2NPTf56gZlu7JPg0W1tRnFG/vsfDzwjwBgIAAA='; - const osxHash = '~~H4sIAAAAAAAAE3VVTY/bNhD9LzwrWafb9qDb2ruLGPBm3diLHoqgGJMjiTDFUcmhvUrR/15Q31Kcm/jecIbz5kP/ClBKsyYL5iv+E9DzHhyUXqR/fUsEWDA1a+k3ZAzKaPcFShSpEBPy6ECet2Xl0HtNVqQZGI/RQO0o1/IIee8vMG0oWHb1Dmw+WJ6IziW481aSPWCM1IaY4m/WTxgJTh24NvEtBZjsQ4E6L7hjjpoNPkgZH3TSRnO9wwsakf6eCDmksmbbu6icLsHVYkqPmY5Y43gJHvT3AbMM2qITqfj0y2r1Au9/asVFR6HlY13hqIdstRCpkAA+7Y53wccLwTOVG3Cq883w0IQTqfjbo8lEIhR9Id7B93pHoAY1lfZwMrgGa9H5EXaQ8eNpOKNVFWkbBb1erx9B0Qk/SirvZKFLdPABKn03ZinijYt2ZEu0XRXwXZqgUMVXdil10JhjBsacQJ6fxnAiERkCBze7mWnD6J4ug/cWWAdt1B5sLF/TQCWwlgO9IwmdKgYznuC5liIV5AZoFsdvGn1n0KGg61NZcT1olAfmppq/votEFAhqcFNohRuGrZqfx8S1XShhwOYBcuzL3Z/vMIproKbQ9EcMF6oIEagXcnizUS3xYrrImjqmsO6mZlC3S4bc4kIFubaNeg9Wl83HEAdyVGJq8mRjU41dNjJ/BLCsuYltb/BdTh3QFGQk3zweCyzxfrxoQGJBRqF7c6ZtBYc+GPZ7dPtGwN8S4RGcLJ41mr4CHiVZBa4eMxygAwUnsQc5CrMmp6bz4SfS+eemI25zr3auaySf+w6bYNuFzaF58Qw6EsfF2yQ3EuT4ERgfvPwBe8Qb4AspnelJbRoCMwgmjpLq77VEW8g9VaGaXWjxr2AVlQcoK6MnG7oxiKN5IMcz9Lmb5BnYv2iZQo//kEYbdg6hR3ch7fZERqSfVqvVgmheiSK9b/F26y8cN+AiXNcKooDr2YtviWDIfdtrP9+E0UZEU5cjx0180XFRiAFbDgjHto5rKf6Y0MfVpJBBG3/Ed36tuq2lujolguNTPyMobfPufyWK+0jELml67khxyKIYiQged9F19DYEDR5fL+gM1Dttz2NPTf56gZlu7JPg0W1tRnFG/vsfDzwjwBgIAAA='; + const windowsHash = '~~H4sIAAAAAAAACnVVTY/bNhD9Lzw7Wafb9qDb2ruLGPBm3diLHoqgGJMjiTDFUcmhvUrR/16Q+nacm/TecIbz5oP/ClBKsyYL5iv+E9DzDhxUXmR/fVsIsGAa1tKvyRiU0e4LVCgyISbkwYE8baraofearMhyMB6jgdpSoeUBit5fYFpTsOyaLdhisDwSnSpwp40ku8cYqQ0xxd+snzASnNpzY+JdSjD5hxJ1UXLHHDQbfJAyXuiojeZmi2c0Ivt9IeSQyopt76J2ugLXiCk9ZjpiyfE1uNffB8wyaItOZOLTL8vlC7z/qRWXHYWWD02Nox6y1UJkQgL4rPu9Cz4eCJ6pWoNTnW+GhxROZOJvjyYXC6HoC/EWvjdbAjWoqbSHo8EVWIvOj7CDnB+Pwz9aVZO2UdDL5fIRFB3xo6TqTpa6QgcfoNZ3Y5YinjhrR7ZC21UB36UJClW8ZZdSB4055mDMEeTpaQwnFiJH4OBmJ3NtGN3TefDeAqugjdqBjeVLDVQBaznQW5LQqWIw5wleaCkyQW6AZnH8Ouk7g/YlXZ6qmptBoyIwp2r++i4WokRQg5tSK1wzbNT8f0xc2yslDNgiQIF9ufv/O4ziGmgopP6I4UIdIQL1Qg5vNqolvpousqaJKay6qRnU7ZIhd3WghkLbpN6D1VX6GOJAgUpMTZ5sbKqxy0bmjwCWNafY9gbf5dQBqSAj+ebxUGKF9+NBAxJLMgrdmzNtKzj0wbDfodslAX9bCI/gZPms0fQV8CjJKnDNmOEA7Sk4iT3IUZgVOTWdD1/S5ZmI0T3qs1ax7BOmF9U/p165zb3aueLJZd97E2xzZbNPucygA3FcySntkSDHj8D44OUP2CPeAF9I6VxPqpYIzCGYOGSqP9cSbYl3VId6dqDFv4JVVO2hqo2e7O5kEId2T45n6HM34zOwv9F1Cj3+Qxpt2DmEHt2ZtNsRGZF9Wi6XV0S6JYrsvsXb9+DKcQKvwnVNIkq4nLz4thAMhW+78Oc7MtqIaOoK5LijzzquEDFg16PDseHjwopPFvq4tBQyaOMP+M6vdbfPVFenheB41c8IStuie8lEeR+J2CWp5w4Uxy+KsRDB4za6jt6GoMHj6xmdgWar7Wnsqcl7GJjpxqYJHt3G5hSn57//AaZjTZUyCAAA'; + const osxHash = '~~H4sIAAAAAAAAA3VVTY/bNhD9Lzw7Wafb9qDb2ruLGPBm3diLHoqgGJMjiTDFUcmhvUrR/16Q+nacm/TecIbz5oP/ClBKsyYL5iv+E9DzDhxUXmR/fVsIsGAa1tKvyRiU0e4LVCgyISbkwYE8baraofearMhyMB6jgdpSoeUBit5fYFpTsOyaLdhisDwSnSpwp40ku8cYqQ0xxd+snzASnNpzY+JdSjD5hxJ1UXLHHDQbfJAyXuiojeZmi2c0Ivt9IeSQyopt76J2ugLXiCk9ZjpiyfE1uNffB8wyaItOZOLTL8vlC7z/qRWXHYWWD02Nox6y1UJkQgL4rPu9Cz4eCJ6pWoNTnW+GhxROZOJvjyYXC6HoC/EWvjdbAjWoqbSHo8EVWIvOj7CDnB+Pwz9aVZO2UdDL5fIRFB3xo6TqTpa6QgcfoNZ3Y5YinjhrR7ZC21UB36UJClW8ZZdSB4055mDMEeTpaQwnFiJH4OBmJ3NtGN3TefDeAqugjdqBjeVLDVQBaznQW5LQqWIw5wleaCkyQW6AZnH8Ouk7g/YlXZ6qmptBoyIwp2r++i4WokRQg5tSK1wzbNT8f0xc2yslDNgiQIF9ufv/O4ziGmgopP6I4UIdIQL1Qg5vNqolvpousqaJKay6qRnU7ZIhd3WghkLbpN6D1VX6GOJAgUpMTZ5sbKqxy0bmjwCWNafY9gbf5dQBqSAj+ebxUGKF9+NBAxJLMgrdmzNtKzj0wbDfodslAX9bCI/gZPms0fQV8CjJKnDNmOEA7Sk4iT3IUZgVOTWdD1/S5ZmI0T3qs1ax7BOmF9U/p165zb3aueLJZd97E2xzZbNPucygA3FcySntkSDHj8D44OUP2CPeAF9I6VxPqpYIzCGYOGSqP9cSbYl3VId6dqDFv4JVVO2hqo2e7O5kEId2T45n6HM34zOwv9F1Cj3+Qxpt2DmEHt2ZtNsRGZF9Wi6XV0S6JYrsvsXb9+DKcQKvwnVNIkq4nLz4thAMhW+78Oc7MtqIaOoK5LijzzquEDFg16PDseHjwopPFvq4tBQyaOMP+M6vdbfPVFenheB41c8IStuie8lEeR+J2CWp5w4Uxy+KsRDB4za6jt6GoMHj6xmdgWar7Wnsqcl7GJjpxqYJHt3G5hSn57//AaZjTZUyCAAA'; + const hash = copyTextArea.value.split('#')[1].trim(); let isCorrectHash = false; - const hash = copyTextArea.value.split('#')[1]; - if (hash === windowsHash || hash === osxHash) { - isCorrectHash = true; - } - expect(isCorrectHash).to.be.true; + let osHash = navigator.platform.startsWith('Win') ? windowsHash : osxHash; + expect(hash).to.equal(osHash); }); it('Clones an object', () => { diff --git a/test/blocks/caas-config/expectedConfigs/defaultConfig.js b/test/blocks/caas-config/expectedConfigs/defaultConfig.js index d424afafeb..ec85d4c1da 100644 --- a/test/blocks/caas-config/expectedConfigs/defaultConfig.js +++ b/test/blocks/caas-config/expectedConfigs/defaultConfig.js @@ -24,6 +24,7 @@ const defaultConfig = { }, detailsTextOption: 'default', setCardBorders: false, + showFooterDivider: false, useOverlayLinks: false, banner: { register: { description: 'Sign Up', url: '#registration' }, diff --git a/test/blocks/caas/utils.test.js b/test/blocks/caas/utils.test.js index c31772ca3c..cc758f77f5 100644 --- a/test/blocks/caas/utils.test.js +++ b/test/blocks/caas/utils.test.js @@ -184,6 +184,7 @@ describe('getConfig', () => { titleHeadingLevel: 'h3', }, setCardBorders: false, + showFooterDivider: false, useOverlayLinks: false, additionalRequestParams: {}, banner: { @@ -379,6 +380,7 @@ describe('getConfig', () => { titleHeadingLevel: 'h3', }, setCardBorders: false, + showFooterDivider: false, useOverlayLinks: false, additionalRequestParams: {}, banner: { @@ -635,6 +637,7 @@ describe('getFloodgateCaasConfig', () => { titleHeadingLevel: 'h3', }, setCardBorders: false, + showFooterDivider: false, useOverlayLinks: false, additionalRequestParams: {}, banner: { From 48ede0004042451832b5d81e5cd6df79a57be7f0 Mon Sep 17 00:00:00 2001 From: Sanjay Rai Date: Tue, 14 May 2024 03:07:39 -0700 Subject: [PATCH 08/14] MWPW-147594: Consumers mappings for origin not being sent when using sidekick (#2244) * Fix for origin always being upper cased * Update tools/send-to-caas/send-utils.js changing to const Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Okan Sahin <39759830+mokimo@users.noreply.github.com> --- tools/send-to-caas/send-utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/send-to-caas/send-utils.js b/tools/send-to-caas/send-utils.js index 76e50a3c7d..2b30e8b967 100644 --- a/tools/send-to-caas/send-utils.js +++ b/tools/send-to-caas/send-utils.js @@ -193,8 +193,9 @@ const getOrigin = (fgColor) => { cc: 'hawks', dc: 'doccloud', }; - if (mappings[origin] || origin) { - return mappings[origin] || origin; + const originLC = (mappings[origin] || origin).toLowerCase(); + if (originLC) { + return originLC; } if (window.location.hostname.endsWith('.hlx.page')) { From fe2bab3422b8c2d249ef6aeeed9137e4819c43d1 Mon Sep 17 00:00:00 2001 From: Okan Sahin <39759830+mokimo@users.noreply.github.com> Date: Tue, 14 May 2024 14:20:15 +0200 Subject: [PATCH 09/14] Stage automation, update the body after merging another PR in (#2289) * Stage process improvements * Remove team reviewers * Formatting * Simplify PR bodies --------- Co-authored-by: Robert Bogos <146744221+robert-bogos@users.noreply.github.com> --- .github/workflows/merge-to-stage.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge-to-stage.js b/.github/workflows/merge-to-stage.js index 4340921b88..78ed0ec6d4 100644 --- a/.github/workflows/merge-to-stage.js +++ b/.github/workflows/merge-to-stage.js @@ -132,7 +132,7 @@ const merge = async ({ prs }) => { merge_method: 'squash', }); } - body = `- [${title}](${html_url})\n${body}`; + body = `- ${html_url}\n${body}`; const isHighImpact = labels.includes(LABELS.highImpact); if (isHighImpact && process.env.SLACK_HIGH_IMPACT_PR_WEBHOOK) { await slackNotification( @@ -184,8 +184,7 @@ const openStageToMainPR = async () => { }); for (const pr of pullRequestData) { - if (!body.includes(pr.html_url)) - body = `- [${pr.title}](${pr.html_url})\n${body}`; + if (!body.includes(pr.html_url)) body = `- ${pr.html_url}\n${body}`; } } @@ -227,12 +226,22 @@ const main = async (params) => { try { const stageToMainPR = await getStageToMainPR(); console.log('has Stage to Main PR:', !!stageToMainPR); + if (stageToMainPR) body = stageToMainPR.body; if (stageToMainPR?.labels.some((label) => label.includes(LABELS.SOTPrefix))) return console.log('PR exists & testing started. Stopping execution.'); const prs = await getPRs(); await merge({ prs: prs.filter(({ labels }) => isHighPrio(labels)) }); await merge({ prs: prs.filter(({ labels }) => !isHighPrio(labels)) }); if (!stageToMainPR) await openStageToMainPR(); + if (body !== stageToMainPR?.body) { + console.log("Updating PR's body..."); + await github.rest.pulls.update({ + owner, + repo, + pull_number: stageToMainPR.number, + body: body, + }); + } console.log('Process successfully executed.'); } catch (error) { console.error(error); From 47c10b40e2dae2dc8c0877a96b925e69eb15a521 Mon Sep 17 00:00:00 2001 From: Okan Sahin <39759830+mokimo@users.noreply.github.com> Date: Tue, 14 May 2024 14:21:48 +0200 Subject: [PATCH 10/14] Remove label requirements & merge workflows (#2288) Remove label & merge workflows Co-authored-by: Robert Bogos <146744221+robert-bogos@users.noreply.github.com> --- .../workflows/auto-merge-main-to-stage.yml | 23 ------------------- .github/workflows/enforce-labels.yml | 15 ------------ 2 files changed, 38 deletions(-) delete mode 100644 .github/workflows/auto-merge-main-to-stage.yml delete mode 100644 .github/workflows/enforce-labels.yml diff --git a/.github/workflows/auto-merge-main-to-stage.yml b/.github/workflows/auto-merge-main-to-stage.yml deleted file mode 100644 index 178a76539f..0000000000 --- a/.github/workflows/auto-merge-main-to-stage.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: PRs to main -on: - pull_request: - branches: [main] - types: [closed] -jobs: - merge-main-to-stage: - if: github.event.pull_request.merged == true - timeout-minutes: 2 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set Git config - run: | - git config user.email "github-actions@github.com" - git config user.name "github-actions" - - name: Merge main to stage - run: | - git fetch - git checkout stage - git pull - git merge --no-ff main -m "Auto-merge main to stage" - git push diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml deleted file mode 100644 index 4216ad7e80..0000000000 --- a/.github/workflows/enforce-labels.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Enforce PR labels - -on: - pull_request: - types: [labeled, unlabeled, opened, synchronize] -jobs: - enforce-label: - runs-on: ubuntu-latest - steps: - - uses: yogevbd/enforce-label-action@2.1.0 - with: - REQUIRED_LABELS_ANY: "verified,trivial,needs-verification,zero-impact" - REQUIRED_LABELS_ANY_DESCRIPTION: "PR must be labeled with 'trivial', 'zero-impact', 'needs-verification', or 'verified'" - BANNED_LABELS: "do not merge,duplicate,invalid,wontfix" - BANNED_LABELS_DESCRIPTION: "This PR has a banned label, if a PR is not ready or should not be merged, please close it and open a new one." From a92623717634f55700b5364929644084a29560d0 Mon Sep 17 00:00:00 2001 From: Cody Lloyd <119891065+colloyd@users.noreply.github.com> Date: Tue, 14 May 2024 08:01:47 -0600 Subject: [PATCH 11/14] Quiz entry block (#2294) * Initial quiz-entry block with ml field * MWPW-144810: Quiz Entry - Add option cards and text to the block (#2095) * Quiz entry block (#2103) * MWPW-144810: Quiz Entry - Add option cards and text to the block * MWPW-144810: Add the text to strings.xlsx for title, subtitle, ML field default, card instruction bar and the button * MWPW-146243 - Quiz entry code optimization (#2121) * MWPW-146243 - Quiz entry code optimization * Restores code optimization that was lost in previous PRs Resolves: [MWPW-146243](https://jira.corp.adobe.com/browse/MWPW-146243) * Update utils.js * Update quiz-entry.js Set button to use string values * Update quiz-entry.js Fixed to use new strings object * MWPW-146034 - Quiz entry block accessibility (#2139) * resolved accessibility concerns when the ml input is used * general code refinements for more clarity, specifically for getting string values Resolves: [MWPW-146034](https://jira.corp.adobe.com/browse/MWPW-146034) * MWPW-146036 - Rig up quiz entry button (#2190) * Support for ml filtering * Debug support using ?debug=quiz-entry * Store quizState in local storage and redirect to the quiz Resolves: [MWPW-146036](https://jira.corp.adobe.com/browse/MWPW-146036) * Quiz entry block (#2204) * MWPW-144810: Quiz Entry - Add option cards and text to the block * MWPW-144810: Add the text to strings.xlsx for title, subtitle, ML field default, card instruction bar and the button * MWPW-147031:Add Analytics for Quiz Entry Block, MWPW-146080: Integrate Auto-Complete for Open Text Field on UAR Exposed Front Door * fix eslint * fix code according feedbacks * MWPW-144022: Quiz entry block (#2227) * carousel starts * got buttons working * MWPW-144022: Prototype carousel refinement, keybord controls updated * linting fixes * MWPW-147482 - ML Input Bulletproofing (#2242) * add support for fallback fi codes * add lana logging for ml field failures * fix so the redirect checks for maxQuestions Resolves: [MWPW-147482](https://jira.corp.adobe.com/browse/MWPW-147482) **Test URLs:** - Before: https://main--milo--adobecom.hlx.page/?martech=off - After: https://--milo--adobecom.hlx.page/?martech=off * MWPW-147683 - CSS Cleanup (#2267) * MWPW-147683 - CSS Cleanup * Final pass on the css * Edits to markup where necessary Resolves: [MWPW-147683](https://jira.corp.adobe.com/browse/MWPW-147683) * pr feedback for vars and eslint errors * more PR feedback on icon placement * pr feedback for button border * cleaned up the carousel widths so it's consistent it all times as it was previously 8px short. * pr feedback on the location of the input clear X. * PR feedback - reduced border on input, fixed a card disable bug, addressed card layout in tablet * carousel starts * got buttons working * MWPW-144022: Prototype carousel refinement, keybord controls updated * linting fixes * Tests * working tests update * Small font size fixes that design has asked for * linting * linting * Update quiz-entry.js with default vals * Bring back debug * debugging debug * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/quiz-entry.test.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/quiz-entry.test.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update test/blocks/quiz-entry/mocks/mock-data.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * added quiz-entry to utils.js (#2296) Co-authored-by: Denys Fedotov * MWPW-148206: Update Spectra ML host from cchome-dev to cchome for PROD --------- Co-authored-by: Jacky Sun <67350368+JackySun9@users.noreply.github.com> Co-authored-by: Brad Johnson Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Denys Fedotov Co-authored-by: Denys Fedotov Co-authored-by: Jacky Sun --- libs/blocks/quiz-entry/mlField.js | 52 + libs/blocks/quiz-entry/quiz-entry.css | 518 ++++++++ libs/blocks/quiz-entry/quiz-entry.js | 383 ++++++ libs/blocks/quiz-entry/quizPopover.js | 31 + libs/blocks/quiz-entry/quizoption.js | 121 ++ libs/blocks/quiz-entry/utils.js | 110 ++ libs/blocks/quiz/utils.js | 21 +- libs/utils/utils.js | 1 + test/blocks/quiz-entry/mocks/index.html | 22 + .../mocks/invalid-user-selection.json | 8 + test/blocks/quiz-entry/mocks/mock-data.js | 1039 +++++++++++++++++ test/blocks/quiz-entry/mocks/mock-states.js | 139 +++ test/blocks/quiz-entry/mocks/questions.json | 529 +++++++++ test/blocks/quiz-entry/mocks/quiz.html | 24 + .../quiz-entry/mocks/result-resources.json | 207 ++++ test/blocks/quiz-entry/mocks/strings.json | 506 ++++++++ test/blocks/quiz-entry/quiz-entry.test.js | 159 +++ 17 files changed, 3866 insertions(+), 4 deletions(-) create mode 100644 libs/blocks/quiz-entry/mlField.js create mode 100644 libs/blocks/quiz-entry/quiz-entry.css create mode 100644 libs/blocks/quiz-entry/quiz-entry.js create mode 100644 libs/blocks/quiz-entry/quizPopover.js create mode 100644 libs/blocks/quiz-entry/quizoption.js create mode 100644 libs/blocks/quiz-entry/utils.js create mode 100644 test/blocks/quiz-entry/mocks/index.html create mode 100644 test/blocks/quiz-entry/mocks/invalid-user-selection.json create mode 100644 test/blocks/quiz-entry/mocks/mock-data.js create mode 100644 test/blocks/quiz-entry/mocks/mock-states.js create mode 100644 test/blocks/quiz-entry/mocks/questions.json create mode 100644 test/blocks/quiz-entry/mocks/quiz.html create mode 100644 test/blocks/quiz-entry/mocks/result-resources.json create mode 100644 test/blocks/quiz-entry/mocks/strings.json create mode 100644 test/blocks/quiz-entry/quiz-entry.test.js diff --git a/libs/blocks/quiz-entry/mlField.js b/libs/blocks/quiz-entry/mlField.js new file mode 100644 index 0000000000..80f0828f98 --- /dev/null +++ b/libs/blocks/quiz-entry/mlField.js @@ -0,0 +1,52 @@ +import { html } from '../../deps/htm-preact.js'; +import { getConfig } from '../../utils/utils.js'; + +export const getMLResults = async (endpoint, apiKey, threshold, input, count, validFiCodes) => { + const { env } = getConfig(); + const subdomain = env === 'prod' ? 'cchome' : 'cchome-dev'; + const apiUrl = `https://${subdomain}.adobe.io/int/v1/models`; + const params = { + endpoint, + contentType: 'application/json', + payload: { + data: { + input, + num_items: count || 10, + given_prod_list: validFiCodes, + }, + }, + }; + + const result = await fetch(apiUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': apiKey, + }, + body: JSON.stringify(params), + }) + .then((response) => response.json()) + .catch((error) => window.lana.log(`ERROR: Fetching fi codes ${error}`)); + + let value; + let highestProb = null; + if (result) { + result.filtered = result?.data?.filter((item) => { + let isValid = false; + if (!highestProb) { + highestProb = item.prob; + isValid = true; + } else if (item.prob / highestProb > threshold) { + isValid = true; + } + return isValid; + }); + value = result; + } else { + value = { errors: [{ title: 'Unable to fetch fi codes' }] }; + } + return value; +}; + +export const mlField = ({ cardsUsed, onMLInput, onMLEnter, placeholderText, onClearClick }) => html` + `; diff --git a/libs/blocks/quiz-entry/quiz-entry.css b/libs/blocks/quiz-entry/quiz-entry.css new file mode 100644 index 0000000000..858604ce0d --- /dev/null +++ b/libs/blocks/quiz-entry/quiz-entry.css @@ -0,0 +1,518 @@ +.quiz-container { + align-items: center; + color: var(--color-black); + display: flex; + flex-direction: column; + padding: var(--spacing-xxxl) var(--spacing-xl); +} + +.quiz-container *{ + box-sizing: border-box; +} + +.quiz-heading-container { + color: #2C2C2C; + margin-bottom: var(--spacing-m); + text-align: center; +} + +.quiz-title { + font-size: 28px; + line-height: 36px; + font-weight: var(--type-heading-all-weight); + margin-bottom: 8px; +} + +.quiz-subtitle { + font-size: 20px; + line-height: 30px; +} + +.quiz-question-container { + display: flex; + flex-flow: row wrap; + justify-content: center; + margin-bottom: var(--spacing-xl); + max-width: 1130px; + width: 100%; +} + +.quiz-input-container { + display: flex; + flex-flow:row nowrap; + justify-content: center; + max-width: 480px; + position: relative; + width: 100%; +} + +.quiz-input { + background: url("data:image/svg+xml,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cg%20clip-path%3D%22url%28%23clip0_796_4337%29%22%3E%0A%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M15.77%2014.7094L11.2357%2010.1751C12.1742%208.96682%2012.6169%207.44625%2012.4736%205.92302C12.3304%204.39978%2011.6119%202.98841%2010.4646%201.97626C9.31732%200.964113%207.82737%200.427296%206.29816%200.475108C4.76895%200.52292%203.31545%201.15177%202.23361%202.23361C1.15177%203.31545%200.52292%204.76895%200.475108%206.29816C0.427296%207.82737%200.964113%209.31732%201.97626%2010.4646C2.98841%2011.6119%204.39978%2012.3304%205.92302%2012.4736C7.44625%2012.6169%208.96682%2012.1742%2010.1751%2011.2357L14.7094%2015.77C14.85%2015.9107%2015.0408%2015.9897%2015.2397%2015.9897C15.4386%2015.9897%2015.6293%2015.9107%2015.77%2015.77C15.9106%2015.6294%2015.9896%2015.4386%2015.9896%2015.2397C15.9896%2015.0408%2015.9106%2014.8501%2015.77%2014.7094ZM6.49998%2011C5.60997%2011%204.73994%2010.7361%203.99992%2010.2416C3.2599%209.74716%202.68312%209.04436%202.34253%208.22209C2.00193%207.39982%201.91282%206.49502%202.08645%205.62211C2.26008%204.74919%202.68867%203.94737%203.318%203.31803C3.94734%202.6887%204.74916%202.26011%205.62208%202.08648C6.49499%201.91285%207.39979%202.00196%208.22206%202.34256C9.04433%202.68315%209.74713%203.25993%2010.2416%203.99995C10.7361%204.73997%2011%205.61%2011%206.50001C10.9986%207.69308%2010.5241%208.83689%209.68048%209.68051C8.83686%2010.5241%207.69305%2010.9987%206.49998%2011Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fg%3E%0A%3Cdefs%3E%0A%3CclipPath%20id%3D%22clip0_796_4337%22%3E%0A%3Crect%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22white%22%2F%3E%0A%3C%2FclipPath%3E%0A%3C%2Fdefs%3E%0A%3C%2Fsvg%3E") no-repeat #fff; + background-position: center right 24px; + border: 2px solid #e6e6e6; + border-radius: 40px; + color: var(--text-color); + cursor: pointer; + font-size: var( --type-body-s-size); + height: 56px; + line-height: var(--type-heading-m-lh); + padding: 0 var(--spacing-xxl) 0 var(--spacing-s); + width: 100%; +} + +.quiz-input::placeholder { + color: var(--text-color); + font-size: var( --type-body-s-size) !important; + font-style: italic; +} + +.quiz-input:focus-visible { + outline: 4px solid #4B75FF; + outline-offset:-1px; +} + +.quiz-input:disabled { + background-color: #fafafacc; + cursor: not-allowed; + outline: none; + opacity: 0.5; +} + +.quiz-input-clear { + background: url("data:image/svg+xml,%0A%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Crect id='Frame' x='4.14' y='3.77' width='12' height='12' style='fill:red;fill-opacity:0'/%3E%3Cg id='Line'%3E%3Cpath d='M14.88,13.16a1,1,0,0,1,0,1.35,1,1,0,0,1-.67.27.94.94,0,0,1-.67-.27l-3.4-3.4-3.39,3.4a1,1,0,0,1-1.35,0,1,1,0,0,1,0-1.35L8.8,9.77,5.4,6.37A1,1,0,0,1,5.4,5,1,1,0,0,1,6.75,5l3.39,3.39L13.54,5a.95.95,0,1,1,1.34,1.34l-3.39,3.4Z' style='fill:%236e6e6e'/%3E%3C/g%3E%3C/svg%3E") center no-repeat #fff; + background-size: 50%; + border-radius: 50%; + cursor: pointer; + height: 52px; + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + width: 52px; +} + +.quiz-input-clear.hidden { + display: none; +} + +.popover-container { + left: 50%; + position: absolute; + transform: translateX(-50%); + width: 100%; + z-index: 10; +} + +.popover-container.popover-bottom { + top: 100%; +} + +.popover-content { + background-color: var(--color-white); + padding: 20px; + max-height: 404px; + overflow: hidden; + text-align: left; + border-radius: 4px; + border: 2px solid #E6E6E6; + margin-top: 8px; + box-sizing: border-box; +} + +.popover-content div:hover { + background-color: #f0f0f0; /* Highlight color on hover */ + text-decoration: underline; +} + +.popover-item { + cursor: pointer; + font-size: var(--type-detail-l-size); + font-weight: 400; + line-height: var(--type-heading-s-lh); + color: var(--link-color-dark); +} + +.quiz-directions { + align-items: center; + background: linear-gradient(90deg, #E200D9 1.24%, #E84601 100%); + border-radius: 8px; + color: #FFF; + display: flex; + font-size: 17px; + font-weight: 900; + height: 40px; + justify-content: center; + line-height: 30px; + margin: var(--spacing-m) 0 8px; + width: 100%; +} + +.quiz-options-container { + display: flex; + flex-flow: row wrap; + position: relative; + max-width: 320px; + width: 100%; +} + +.quiz-options-container:focus-visible { + outline: 4px solid #4B75FF; + outline-offset: 2px; +} + +.carousel-slides { + display: flex; + gap: 8px; + justify-content: center; + overflow: hidden; + padding: 8px; + position: relative; + width: 100%; +} + +.carousel-arrow { + background-color: #fff; + background-image: url('https://main--milo--adobecom.hlx.page/libs/blocks/carousel/img/arrow.svg'); + background-size: 15px; + background-position: 50% 50%; + background-repeat: no-repeat; + border: none; + border-radius: 50%; + box-shadow: 10px 10px 15px -5px rgba(0 0 0 /23%); + cursor: pointer; + height: 63px; + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 63px; + z-index: 1; +} + +.arrow-next { + right: -32px; +} + +.arrow-prev { + left: -32px; + transform: rotate(180deg) translateY(50%); +} + +.arrow-next.rtl { + transform: rotate(180deg) translateY(50%); + +} + +.arrow-prev.rtl { + transform: rotate(0deg) translateY(-50%); +} + +.quiz-options-container:focus-visible, +.carousel-arrow:focus-visible { + outline: 4px solid #4B75FF; + outline-offset: -1px; +} + +.quiz-option { + flex: 0 0 138px; + flex-direction: column; + height: 100%; + margin: 0; + align-items: stretch; + border: none; + border-radius: 0.5rem; + cursor: pointer; + display: flex; + font-family: inherit; + padding: 0; + user-select: none; + min-height: 186px; + outline: none; + position: relative; +} + +.quiz-option-icon { + align-items: center; + background-color: var(--quiz-icon-bg); + border-radius: 0.5rem; + display: flex; + line-height: 0; + padding: 0 24px; +} + +.quiz-option-icon img { + height: var(--icon-size-l); + width: var(--icon-size-l); + max-width: var(--icon-size-l); +} + +.quiz-option.has-icon .no-icon-default { + display: none; +} + +.quiz-option-image { + display: flex; + align-items: center; + border-radius: 0.5rem; + justify-content: center; + margin: 0; + height: 100%; + filter: brightness(33%); +} + +.quiz-option-text-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + padding: 0 1rem; +} + +.quiz-option-title { + color: white; + font-size: var(--type-detail-l-size); + font-weight: 900; + line-height: var(--type-heading-s-lh); + margin: 0 0 4px; + text-align: start; +} + +.quiz-option-text { + color: white; + font-size: 14px; + font-weight: 400; + line-height: 21px; + margin: 0; + text-align: start; +} + +.quiz-option:hover .quiz-option-icon { + background-color: color-mix(in srgb, var(--quiz-icon-bg) 70%, var(--color-white)); +} + +.quiz-option:focus-visible .quiz-option-icon { + background-color: color-mix(in srgb, var(--quiz-icon-bg) 80%, var(--color-white)); +} + +.quiz-option.selected { + border: 5px solid #FC00F2; + border-radius: 13px; +} + +.quiz-option.selected::before { + background: url("data:image/svg+xml,%3Csvg%20width%3D%2225%22%20height%3D%224%22%20viewBox%3D%220%200%2025%204%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cpath%20d%3D%22M2%202H23%22%20stroke%3D%22white%22%20stroke-width%3D%224%22%20stroke-linecap%3D%22round%22%2F%3E%0A%3C%2Fsvg%3E") no-repeat; + background-size: 20px 4px; + content: " "; + height: 4px; + position: absolute; + right: 20px; + top: 20px; + width: 20px; + z-index: 1; +} + +.quiz-option.selected .quiz-option-icon { + background-color: color-mix(in srgb, var(--quiz-icon-bg) 70%, var(--color-white)); +} + +.quiz-option:hover .quiz-option-image, +.quiz-option.selected .quiz-option-image, +.quiz-option:focus-visible .quiz-option-image { + filter: brightness(33%); +} + +.quiz-option:focus-visible::after { + content: " "; + border-radius: 0.5rem; + height: 100%; + outline: 4px solid #4B75FF; + outline-offset: 2px; + position: absolute; + width: 100%; + z-index: -1; +} + +.quiz-option.selected:focus-visible::after { + border-radius: 8px; + outline-offset: 8px; +} + +.quiz-option.disabled { + background-color: #fafafacc; + outline: none; +} + +.quiz-option.disabled .quiz-option-icon, +.quiz-option.disabled .quiz-option-image, +.quiz-option.disabled .quiz-option-text-container{ + opacity: 0.5; + cursor: not-allowed; +} + +.quiz-button-container { + align-items: center; + display: flex; + justify-content: center; +} + +.quiz-button { + background: var(--color-gray-800); + border: 2px solid var(--color-white); + border-radius: 20px; + cursor: pointer; + font-family: inherit; + font-size: 17px; + font-weight: 700; + line-height: 21px; + padding: 9px 16px; +} + +.quiz-button:focus-visible { + outline: 4px solid #4B75FF; +} + +.quiz-button-label { + color: var(--color-white); + font-size: 18px; + font-weight: var(--type-heading-all-weight); + line-height: 22px; +} + +.quiz-button[disabled] { + background: var(--color-gray-400); + cursor: not-allowed; +} + +.quiz-button[disabled] .quiz-button-label{ + color: var(--color-white); +} + +/* Tablet up */ +@media screen and (min-width: 600px) { + .quiz-container { + padding: 80px 64px; + } + + .quiz-input { + height: 66px; + } + + .quiz-input::placeholder { + width: 311px; + height: 30px; + font-size: 20px; + line-height: 30px; + } + + .quiz-options-container { + max-width: none; + } + + .carousel-slides { + justify-content: left; + } + + .carousel-slides.align-right { + justify-content: right; + margin-left: 0; + } + + .quiz-option-icon { + border-radius: 0.5rem; + justify-content: center; + min-height: 126px; + } + + .quiz-option-icon img { + height: var(--icon-size-xl); + width: var(--icon-size-xl); + max-width: 100%; + } + + .quiz-option.has-icon.quiz-option.has-image .no-icon-tablet, + .quiz-option.has-icon .quiz-option-image { + display: none; + } + + .quiz-option.has-icon .no-icon-tablet ~ .quiz-option-image, + .quiz-option.has-icon .no-icon-default { + display: flex; + } + + .quiz-option.selected .quiz-option-text { + font-weight: normal; + } + + .quiz-footer { + margin: 0 0 40px; + } +} + +/* Desktop */ +@media screen and (min-width: 1024px) { + .quiz-container { + padding: 104px 64px; + } + + .quiz-directions { + height: 50px; + } + + .carousel-slides { + justify-content: left; + margin: 0 -8px; + width: calc(100% + 8px); + } + + .carousel-slides.align-right { + justify-content: right; + margin-left: 0; + } + + .quiz-option { + flex: 0 0 232px; + min-height: 232px; + } + + .quiz-option-image { + filter: brightness(55%); + } + + .quiz-option-title { + font-size: 24px; + line-height: 30px; + text-align: center; + } + + .quiz-option-text { + display: none; + text-align: center; + font-size: var(--type-detail-l-size); + line-height: var(--type-heading-s-lh); + } + + .quiz-option:hover .quiz-option-text, + .quiz-option.selected .quiz-option-text , + .quiz-option:focus-visible .quiz-option-text { + display: block; + } + + .quiz-option.has-image .quiz-option-icon { + display: none; + } + + .quiz-option.has-icon .quiz-option-image { + display: flex; + } + + .quiz-step-container.top { + display: flex; + } + + .quiz-step-container.bottom { + display: none; + } +} diff --git a/libs/blocks/quiz-entry/quiz-entry.js b/libs/blocks/quiz-entry/quiz-entry.js new file mode 100644 index 0000000000..8559d7f04e --- /dev/null +++ b/libs/blocks/quiz-entry/quiz-entry.js @@ -0,0 +1,383 @@ +import { render, html, useEffect, useState, useRef } from '../../deps/htm-preact.js'; +import { getQuizEntryData, handleNext, handleSelections } from './utils.js'; +import { mlField, getMLResults } from './mlField.js'; +import { GetQuizOption } from './quizoption.js'; +import { quizPopover, getSuggestions } from './quizPopover.js'; + +const App = ({ + quizPath, + maxQuestions, + analyticsType = null, + questionData = { questions: { data: [] } }, + stringsData = { questions: { data: [] } }, + debug = false, +}) => { + const [dataLoaded, setDataLoaded] = useState(false); + const [quizState, setQuizState] = useState({ userFlow: [], userSelection: [] }); + const [quizLists, setQuizLists] = useState({}); + const [quizData, setQuizData] = useState({}); + const [hasMLData, setHasMLData] = useState(false); + const [mlData, setMLData] = useState({}); + const [mlInputUsed, setMLInputUsed] = useState(false); + const [cardsUsed, setCardsUsed] = useState(false); + const [selectedQuestion, setSelectedQuestion] = useState(null); + const [selectedCards, setSelectedCards] = useState({}); + const questionCount = useRef(0); + const [btnAnalytics, setBtnAnalytics] = useState(null); + const [fiCodeResults, setFiCodeResults] = useState({}); + const [showPopover, setShowPopover] = useState(false); + const [suggestions, setSuggestions] = useState([]); + + const QUIZ_INPUT = '#quiz-input'; + const QUIZ_INPUT_CLEAR = '#quiz-input-clear'; + const fiCodeCount = 3; + const enterKeyCode = 13; + const defaultThreshold = 0; + + let maxSelections = 10; + + const getStringValue = (propName) => { + if (!selectedQuestion?.questions) return ''; + const question = quizLists.strings[selectedQuestion.questions]; + return question?.[propName] || ''; + }; + + const getOptionsValue = (optionsType, prop) => { + const optionItem = quizData.strings[selectedQuestion.questions].data.find( + (item) => item.options === optionsType, + ); + return optionItem && optionItem[prop] ? optionItem[prop] : ''; + }; + + useEffect(() => { + (async () => { + const qMap = {}; + const questionDataArray = questionData?.questions?.data || []; + questionDataArray.forEach((question) => { + qMap[question.questions] = question; + }); + + const strMap = {}; + const stringsDataArray = stringsData?.questions?.data || []; + stringsDataArray.forEach((question) => { + strMap[question.q] = question; + }); + + const qLists = { + questions: qMap, + strings: strMap, + }; + + const qData = { + questions: questionData, + strings: stringsData, + }; + + if (questionDataArray.length > 0) { + setQuizState({ + userFlow: [questionDataArray[0].questions], + userSelection: quizState.userSelection, + }); + setSelectedQuestion(qLists.questions[questionDataArray[0].questions]); + } + setQuizData(qData); + setQuizLists(qLists); + setDataLoaded(true); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + (async () => { + const selectedTotal = Object.keys(selectedCards).length; + if (selectedTotal > 0) { + setCardsUsed(true); + } else { + setCardsUsed(false); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedCards]); + + useEffect(() => { + (async () => { + if (quizState.userFlow && quizState.userFlow.length) { + const currentFlow = [...quizState.userFlow]; + if (currentFlow && currentFlow.length && questionCount.current < maxQuestions) { + quizState.userFlow.shift(); + questionCount.current += 1; + setSelectedQuestion(quizLists.questions[currentFlow.shift()] || []); + } + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [quizState]); + + useEffect(() => { + (async () => { + if (selectedQuestion) { + const mlmap = { mlDetails: {}, mlOptions: [], mlValues: [] }; + quizData.questions[selectedQuestion.questions].data.forEach((row) => { + if (row.type === 'form') { + mlmap.mlDetails = row; + } else if (row.type === 'api_return_code') { + mlmap.mlOptions.push(row); + mlmap.mlValues.push(row.options); + } + }); + setMLData(mlmap); + if (Object.keys(mlmap.mlDetails).length > 0) { + setHasMLData(true); + } else { + setHasMLData(false); + } + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedQuestion]); + + useEffect(() => { + let btnAnalyticsData = ''; + const selectedCardNames = Object.keys(selectedCards); + if (selectedCardNames.length > 0) { + btnAnalyticsData = `Filters|${analyticsType}|${selectedQuestion?.questions}/${selectedCardNames.join('/')}`; + } + + if (fiCodeResults && fiCodeResults.length > 0) { + const fiCodes = fiCodeResults.map((result) => result.ficode); + btnAnalyticsData = `Filters|${analyticsType}|${selectedQuestion?.questions}/interest-${fiCodes.join('-')}`; + } + + setBtnAnalytics(btnAnalyticsData); + }, [selectedQuestion, selectedCards, fiCodeResults, analyticsType]); + + const continueQuiz = async () => { + let selections = {}; + let userFlow = []; + if (mlInputUsed) { + const { mlDetails, mlValues } = mlData; + const mlFieldText = document.querySelector(QUIZ_INPUT).value; + const fiResults = await getMLResults(mlDetails.endpoint, mlDetails['api-key'], mlDetails.threshold || defaultThreshold, mlFieldText, fiCodeCount, mlValues); + const { filtered } = fiResults; + let fallback = []; + let error = 'Cannot connect to the ML endpoint'; + + if (mlDetails.fallback) fallback = mlDetails.fallback.split(','); + if (filtered) { + setFiCodeResults(filtered); + filtered.forEach((item) => { + selections[item.ficode] = true; + }); + } else if (fiResults.errors || fiResults.error_code) { + for (const ficode of fallback) { + selections[ficode] = true; + } + if (fiResults.errors) error = fiResults.errors[0].title; + if (fiResults.error_code) error = fiResults.message; + window.lana.log(`ML results error - ${error}`); + } + + if (debug) { + if (!fiResults.errors && !fiResults.error_code) { + // eslint-disable-next-line no-console + console.log('all', fiResults.data); + // eslint-disable-next-line no-console + console.log('filtered', filtered); + } else { + // eslint-disable-next-line no-console + console.log('fallback codes used', fallback); + } + } + } + + if (cardsUsed) { + userFlow = quizState.userFlow; + selections = selectedCards; + } + + if (Object.keys(selections).length > 0) { + const { nextFlow } = handleNext( + questionData, + selectedQuestion, + selections, + userFlow, + ); + const { nextSelections } = handleSelections( + quizState.userSelection, + selectedQuestion, + selections, + ); + + if (mlInputUsed) { nextSelections[0].isML = true; } + + const currentQuizState = { + userFlow: nextFlow, + userSelection: nextSelections, + }; + localStorage.setItem('stored-quiz-state', JSON.stringify(currentQuizState)); + setQuizState(currentQuizState); + + // eslint-disable-next-line no-console + if (debug) console.log(currentQuizState); + if (questionCount.current === maxQuestions || currentQuizState.userFlow.length === 1) { + if (!debug) { + setSelectedQuestion(null); + window.location = quizPath; + } + } else { + setSelectedCards({}); + setSelectedQuestion(null); + setMLInputUsed(false); + } + } + }; + + const onOptionClick = (option) => () => { + const selected = { ...selectedCards }; + const selectedTotal = Object.keys(selected).length; + + if (selectedTotal >= maxSelections && !selected[option.options]) { + return; + } + + if (!selected[option.options]) { + selected[option.options] = true; + } else { + delete selected[option.options]; + } + + setSelectedCards(selected); + }; + + const onMLInput = async (event) => { + const inputValue = event.target.value; + setMLInputUsed(true); + const { mlDetails } = mlData; + const data = await getSuggestions(mlDetails['ac-endpoint'], mlDetails['ac-client-id'], inputValue, mlDetails['ac-scope']); + if (data && data.suggested_completions && data.suggested_completions.length > 0) { + setSuggestions(data.suggested_completions.slice(0, 5)); + setShowPopover(true); + } + + document.querySelector(QUIZ_INPUT_CLEAR).classList.toggle('hidden', !inputValue.length); + + if (inputValue.length === 0) { + setMLInputUsed(false); + setSuggestions([]); + setShowPopover(false); + } + }; + + const onMLEnter = (event) => { + if (event.keyCode === enterKeyCode) continueQuiz(); + }; + + const onSuggestionClick = (suggestion) => () => { + const input = document.querySelector(QUIZ_INPUT); + input.value = suggestion.name; + setSuggestions([]); + setShowPopover(false); + input.focus(); + }; + + const onClearClick = () => { + document.querySelector(QUIZ_INPUT).value = ''; + document.querySelector(QUIZ_INPUT_CLEAR).classList.add('hidden'); + setMLInputUsed(false); + setSuggestions([]); + setShowPopover(false); + }; + + if (selectedQuestion) { + maxSelections = +selectedQuestion['max-selections']; + } + + if (!dataLoaded || !selectedQuestion) return null; + + return html`
+
+
${quizLists.strings[selectedQuestion.questions].heading}
+
${quizLists.strings[selectedQuestion.questions]['sub-head']}
+
+
+
+ ${hasMLData && html` + <${mlField} + cardsUsed="${cardsUsed}" + onMLInput="${onMLInput}" + onMLEnter="${onMLEnter}" + onClearClick="${onClearClick}" + placeholderText="${getOptionsValue('fi_code', 'title')}"/>`} + ${showPopover && html`<${quizPopover} + suggestions=${suggestions} + position="bottom" + onSuggestionClick=${onSuggestionClick}/>`} +
+
${quizLists.strings[selectedQuestion.questions].text}
+ ${selectedQuestion.questions && html`<${GetQuizOption} + maxSelections=${maxSelections} + options=${quizData.strings[selectedQuestion.questions]} + background=${getStringValue('icon-background-color')} + countSelectedCards=${Object.keys(selectedCards).length} + selectedCards=${selectedCards} + onOptionClick=${onOptionClick} + getOptionsValue=${getOptionsValue} + mlInputUsed=${mlInputUsed}/>`} +
+
+ +
+
`; +}; +export default async function init( + el, + config = { + quizPath: null, + maxQuestions: null, + analyticsType: null, + questionData: null, + stringsData: null, + debug: false, + }, +) { + let quizEntry; + if (config.questionData && config.stringsData) { + quizEntry = config; + } else { + try { + quizEntry = await getQuizEntryData(el); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to load quiz data:', error); + quizEntry = { + quizPath: '', + maxQuestions: 0, + analyticsType: '', + questionData: { questions: { data: [] } }, + stringsData: { questions: { data: [] } }, + debug: false, + }; + } + } + + const params = new URL(document.location).searchParams; + const isDebug = params.get('debug') === 'quiz-entry'; + quizEntry.debug = isDebug; + + el.replaceChildren(); + render(html`<${App} + quizPath=${quizEntry.quizPath || ''} + maxQuestions=${quizEntry.maxQuestions || 0} + analyticsType=${quizEntry.analyticsType || ''} + questionData=${quizEntry.questionData} + stringsData=${quizEntry.stringsData} + debug=${quizEntry.debug || false} + />`, el); +} diff --git a/libs/blocks/quiz-entry/quizPopover.js b/libs/blocks/quiz-entry/quizPopover.js new file mode 100644 index 0000000000..ba4069bf8e --- /dev/null +++ b/libs/blocks/quiz-entry/quizPopover.js @@ -0,0 +1,31 @@ +import { html } from '../../deps/htm-preact.js'; +import { getConfig } from '../../utils/utils.js'; + +export const getSuggestions = async (endpoint, clientId, input, scope) => { + const { locale } = getConfig(); + const localeCode = locale?.ietf ? `${locale.ietf}`.replace('-', '_') : 'en_us'; + const apiUrl = `https://adobesearch.adobe.io/${endpoint}/completions?q[text]=${input}&q[locale]=${localeCode}&scope=${scope}`; + + const response = await fetch(apiUrl, { + method: 'GET', + headers: { 'x-api-key': clientId }, + }); + + if (!response.ok) { + window.lana.log('Failed to fetch suggestions'); + return ''; + } + + const data = await response.json(); + return data; +}; + +export const quizPopover = ({ suggestions, position = 'bottom', onSuggestionClick }) => html`
+
+ ${suggestions.map((suggestion, index) => html` +
+ ${suggestion.name} +
+ `)} +
+
`; diff --git a/libs/blocks/quiz-entry/quizoption.js b/libs/blocks/quiz-entry/quizoption.js new file mode 100644 index 0000000000..a2774c89b0 --- /dev/null +++ b/libs/blocks/quiz-entry/quizoption.js @@ -0,0 +1,121 @@ +import { html, useState, useEffect } from '../../deps/htm-preact.js'; + +export const OptionCard = ({ + text, title, image, icon, iconTablet, iconDesktop, options, + disabled, selected, background, onClick, +}) => { + const getOptionClass = () => { + let className = ''; + if (icon || iconTablet || iconDesktop) className += 'has-icon '; + if (image) className += 'has-image '; + if (background) className += 'has-background '; + if (disabled) className += 'disabled '; + if (selected) className += 'selected '; + return className; + }; + + const getIconHtml = () => html`
+ + ${iconDesktop && html``} + ${iconTablet && html``} + ${`Icon - ${title || text}`} + +
`; + + const imageHtml = image ? html`
` : null; + const titleHtml = title ? html`

${title}

` : null; + const textHtml = text ? html`

${text}

` : null; + + return html``; +}; + +export const GetQuizOption = ({ + options, maxSelections, selectedCards, + onOptionClick, countSelectedCards, getOptionsValue, + background, mlInputUsed, +}) => { + const [index, setIndex] = useState(0); + const [visibleCount, setVisibleCount] = useState(6); + setVisibleCount(window.innerWidth >= 600 ? 6 : 3); + + const isRTL = document.documentElement.getAttribute('dir') === 'rtl'; + + useEffect(() => { + const handleResize = () => setVisibleCount(window.innerWidth >= 600 ? 6 : 3); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + const next = () => { + if (index + visibleCount < options.data.length) { + setIndex(index + 1); + } + }; + + const prev = () => { + if (index > 0) { + setIndex(index - 1); + } + }; + + const handleKey = (e) => { + if (e.key === 'ArrowRight') { + e.preventDefault(); + if (isRTL) { + prev(); + } else { + next(); + } + } else if (e.key === 'ArrowLeft') { + e.preventDefault(); + if (isRTL) { + next(); + } else { + prev(); + } + } else if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + if (e.target && e.target.click) { + e.target.click(); + } + } + }; + + useEffect(() => { + const entry = document.querySelector('.quiz-entry'); + if (entry && entry.querySelector('.no-carousel')) { + entry.removeChild(entry.querySelector('.no-carousel')); + } + }, []); + + return html` +
+ ${index > 0 && html``} + + ${(index + visibleCount < options.data.length) && html``} +
`; +}; diff --git a/libs/blocks/quiz-entry/utils.js b/libs/blocks/quiz-entry/utils.js new file mode 100644 index 0000000000..0d04f20364 --- /dev/null +++ b/libs/blocks/quiz-entry/utils.js @@ -0,0 +1,110 @@ +import { getNormalizedMetadata } from '../quiz/utils.js'; + +export async function fetchJson(path) { + const response = await fetch(path); + return response.json(); +} + +export async function getQuizJson(path) { + try { + const [questions, strings] = await Promise.all( + [fetchJson(`${path}questions.json`), fetchJson(`${path}strings.json`)], + ); + return [questions, strings]; + } catch (ex) { + window.lana?.log(`ERROR: Fetching data for quiz entry ${ex}`); + } + return []; +} + +export const handleNext = (questionsData, selectedQuestion, userInputSelections, userFlow) => { + const allcards = Object.keys(userInputSelections); + let nextFlow = []; + let hasResultTrigger = false; + + allcards.forEach((selection) => { + // for each elem in current selection, find its coresponding + // next element and push it to the next array. + const nextItems = questionsData[selectedQuestion.questions].data; + const getAllSelectedQuestionsRelatedOptions = nextItems.filter( + (nextItem) => nextItem.options === selection, + ); + + getAllSelectedQuestionsRelatedOptions.forEach(({ options, next }) => { + if (options === selection) { + const flowStepsList = next.split(','); + // RESET the queue and add only the next question. + if (flowStepsList.includes('RESET')) { // Reset to intial question + nextFlow = []; // Resetting the nextQuizViews + // eslint-disable-next-line no-param-reassign + userFlow = []; // Resetting the userFlow as well + } + + if (!hasResultTrigger) { + hasResultTrigger = flowStepsList.includes('RESULT'); + } + + const filteredNextSteps = flowStepsList.filter((val) => (val !== 'RESULT' && val !== 'RESET')); + + nextFlow = [...nextFlow, ...filteredNextSteps]; + } + }); + }); + + // Stripping off the next steps that are negated using 'NOT()'. + nextFlow.forEach((nextStep) => { + if (nextStep?.startsWith('NOT(')) { + const stepsToSkip = nextStep?.substring( + nextStep.indexOf('(') + 1, + nextStep.lastIndexOf(')'), + ); + const stepsToSkipArr = stepsToSkip?.split(','); + stepsToSkipArr?.forEach((skip) => { + nextFlow = nextFlow.filter((view) => (view !== skip)); + }); + } + }); + + // Filtering out the NOT() from the nextQuizViews. + nextFlow = nextFlow.filter((view) => view.startsWith('NOT(') === false); + + return { nextFlow: [...new Set([...userFlow, ...nextFlow])] }; +}; + +export const handleSelections = (prevSelections, selectedQuestion, selections) => { + const newSelections = { selectedQuestion, selectedCards: selections }; + let nextSelections = []; + let isNewQuestion = true; + // de-dup any existing data if they use the ml field and cards. + if (prevSelections.length > 0) { + prevSelections.forEach((selection) => { + if (selection.selectedQuestion === selectedQuestion) { + selection.selectedCards = selections; + isNewQuestion = false; + } + }); + nextSelections = prevSelections; + } + + if (isNewQuestion) nextSelections.push(newSelections); + + return { nextSelections }; +}; + +export async function getQuizEntryData(el) { + const blockData = getNormalizedMetadata(el); + const dataPath = blockData.data.text; + const quizPath = blockData.quiz.text; + const maxQuestions = Number(blockData.maxquestions?.text) || 10; + const analyticsType = blockData.analyticstype?.text; + const analyticsQuiz = blockData.analyticsquiz?.text; + const [questionData, stringsData] = await getQuizJson(dataPath); + return { + quizPath, + maxQuestions, + analyticsQuiz, + analyticsType, + questionData, + stringsData, + }; +} diff --git a/libs/blocks/quiz/utils.js b/libs/blocks/quiz/utils.js index 7e66534537..4af0f53590 100644 --- a/libs/blocks/quiz/utils.js +++ b/libs/blocks/quiz/utils.js @@ -61,7 +61,10 @@ export const defaultRedirect = (url) => { window.location.href = url; }; -export const handleResultFlow = async (answers = [], redirectFunc = defaultRedirect) => { +export const handleResultFlow = async ( + answers = [], + redirectFunc = defaultRedirect, +) => { const { destinationPage } = await findAndStoreResultData(answers); const redirectUrl = getRedirectUrl(destinationPage); redirectFunc(redirectUrl); @@ -441,6 +444,7 @@ export const handleNext = (questionsData, selectedQuestion, userInputSelections, export const transformToFlowData = (userSelection) => { const flowData = userSelection.map(({ selectedCards, selectedQuestion }) => [ selectedQuestion.questions, Object.keys(selectedCards)]); + if (userSelection[0].isML) { flowData.push('isML'); } return flowData; }; @@ -473,10 +477,19 @@ export const getAnalyticsDataForLocalStorage = (config) => { formattedResultString = formattedResultString ? `${formattedResultString}|${product}` : product; }); } - answers?.forEach((answer) => { - const eachAnswer = `${answer[0]}/${answer[1].join('/')}`; + + for (let i = 0; i < answers.length - 1; i += 1) { + const answer = answers[i]; + const eachAnswer = i === 0 && answers[answers.length - 1] === 'isML' ? `${answer[0]}/interest-${answer[1].join('-')}` : `${answer[0]}/${answer[1].join('/')}`; formattedAnswerString = formattedAnswerString ? `${formattedAnswerString}|${eachAnswer}` : eachAnswer; - }); + } + + if (answers[answers.length - 1] !== 'isML') { + const answer = answers[answers.length - 1]; + const lastFormattedAnswer = `${answer[0]}/${answer[1].join('/')}`; + formattedAnswerString = formattedAnswerString ? `${formattedAnswerString}|${lastFormattedAnswer}` : `${lastFormattedAnswer}`; + } + const analyticsHash = `type=${analyticsType}&quiz=${analyticsQuiz}&result=${formattedResultString}&selectedOptions=${formattedAnswerString}`; return analyticsHash; }; diff --git a/libs/utils/utils.js b/libs/utils/utils.js index 8b3be3e178..2e22650ee2 100644 --- a/libs/utils/utils.js +++ b/libs/utils/utils.js @@ -64,6 +64,7 @@ const MILO_BLOCKS = [ 'preflight', 'promo', 'quiz', + 'quiz-entry', 'quiz-marquee', 'quiz-results', 'tabs', diff --git a/test/blocks/quiz-entry/mocks/index.html b/test/blocks/quiz-entry/mocks/index.html new file mode 100644 index 0000000000..2fedf2fe64 --- /dev/null +++ b/test/blocks/quiz-entry/mocks/index.html @@ -0,0 +1,22 @@ +
+
+
data
+
/drafts/quiz/quiz-entry/
+
+
+
quiz
+
/drafts/quiz/
+
+
+
max-questions
+
1
+
+
+
analytics-type
+
cc:app-reco
+
+
+
analytics-quiz
+
UARv4
+
+
diff --git a/test/blocks/quiz-entry/mocks/invalid-user-selection.json b/test/blocks/quiz-entry/mocks/invalid-user-selection.json new file mode 100644 index 0000000000..fc081a0f98 --- /dev/null +++ b/test/blocks/quiz-entry/mocks/invalid-user-selection.json @@ -0,0 +1,8 @@ +{ + "selectedQuestion": { + "questions": "q-category", + "max-selections": "3", + "min-selections": "1" + }, + "selectedCards": { "invalid-option": true } +} diff --git a/test/blocks/quiz-entry/mocks/mock-data.js b/test/blocks/quiz-entry/mocks/mock-data.js new file mode 100644 index 0000000000..01d7a933d6 --- /dev/null +++ b/test/blocks/quiz-entry/mocks/mock-data.js @@ -0,0 +1,1039 @@ +const resultsMock = { + strings: { + 'q-video': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'social', + title: '', + text: 'Create, edit, and share on social', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/1-PR-CreateEditShare.png', + }, + { + options: 'pro', + title: '', + text: 'Make pro-level edits for high-quality results', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/2-PR-ProLevelEdits.png', + }, + { + options: 'movement', + title: '', + text: 'Create graphics and transitions that move', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/3-AE-TitlesAndTransitions.png', + }, + { + options: 'animate', + title: '', + text: 'Make animations for cartoons or games', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/4-AN-Animations.png', + }, + { + options: 'sound', + title: '', + text: 'Edit, mix, and add sound effects', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/5-AU-SoundEffects.png', + }, + ], + }, + 'q-3d': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'stage', + title: '', + text: 'Assemble, stage, and render 3D scenes', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/3-Stager@1x.png', + }, + { + options: 'texture', + title: '', + text: 'Texture 3D assets in real time', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/2-Painter@1x.png', + }, + { + options: 'materials', + title: '', + text: 'Create 3D materials from real-life images', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/5-Sampler@1x.png', + }, + { + options: 'model', + title: '', + text: 'Create 3D models with digital clay', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/1-Modeler@1x.png', + }, + { + options: 'assets', + title: '', + text: 'Design 3D assets and materials', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/4-Designer@1x.png', + }, + ], + }, + 'q-category': { + total: 7, + offset: 0, + limit: 7, + data: [ + { + options: 'fi_code', + title: 'Describe your interest here', + text: 'Ask our AI assistant', + icon: 'https://milo.adobe.com/drafts/quiz/quiz-ai/search.svg', + image: '', + }, + { + options: 'photo', + title: 'Photography', + text: 'Edit or organize my photos', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/photography.png', + }, + { + options: 'video', + title: 'Video', + text: 'Create and edit video or audio', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/video.png', + }, + { + options: 'design', + title: 'Graphic design', + text: 'Design layouts or websites', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/design.png', + }, + { + options: 'illustration', + title: 'Illustration', + text: 'Paint, draw, or create illustrations', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/illustration.png', + }, + { + options: 'pdf', + title: 'PDFs', + text: 'Create, edit, or sign PDFs', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/pdf.png', + }, + { + options: '3d', + title: '3D/AR', + text: 'Model, texture, and render 3D assets and scenes', + icon: '', + image: 'https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/3dar.png', + }, + ], + }, + questions: { + total: 10, + offset: 0, + limit: 10, + data: [ + { + q: 'q-category', + heading: 'Not sure which apps are best for you?', + 'sub-head': 'Tell us what you’re interested in. We’ll help you figure it out.', + btn: 'Continue', + text: 'Or pick up to 3 below', + background: 'https://milo.adobe.com/drafts/quiz/quiz-2/quiz-background.jpeg', + footerFragment: '', + }, + { + q: 'q-fallback', + heading: "We're sorry our assistant couldn't help today.", + 'sub-head': 'Please choose up to three options.', + btn: 'Next', + text: '', + background: 'https://milo.adobe.com/drafts/quiz/quiz-2/quiz-background.jpeg', + footerFragment: '', + }, + { + q: 'q-photo', + heading: 'What do you want to do with photos?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Photo%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: 'https://milo.adobe.com/fragments/quiz/sample-uar-fragments/footer/footer1', + }, + { + q: 'q-video', + heading: 'What do you want to do with video?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Photo%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-design', + heading: 'What do you want to do with design?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Design%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-illustration', + heading: 'What do you want to do with illustration?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Illustration%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-pdf', + heading: 'What do you want to do with PDFs?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Acrobat%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-3d', + heading: 'What do you want to do with 3D/AR?', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-3D-AR%20BKGD?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-rather', + heading: 'For your projects, would you rather:', + 'sub-head': 'Pick one.', + btn: 'Next', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q3-Learn%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: '', + }, + { + q: 'q-customer', + heading: 'What else are you looking for today?', + 'sub-head': 'Pick one.', + btn: 'Get your results', + text: '', + background: 'https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q4%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920', + footerFragment: 'https://milo.adobe.com/fragments/quiz/sample-uar-fragments/footer/footer2', + }, + ], + }, + 'q-rather': { + total: 2, + offset: 0, + limit: 2, + data: [ + { + options: 'template', + title: '', + text: 'Edit quickly and customize templates', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/1-Templates.png', + }, + { + options: 'custom', + title: '', + text: 'Take the time to control every detail', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/2-CustomDesigns.png', + }, + ], + }, + 'q-photo': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'organize', + title: '', + text: 'Get them sorted and organized', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/1-LR-StoreAndOrganize.png', + }, + { + options: 'batch', + title: '', + text: 'Edit lots of photos quickly', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/2-LR-ApplyFilters.png', + }, + { + options: 'edit', + title: '', + text: 'Edit and finesse the smallest details', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/3-PS-RemoveObjects.png', + }, + { + options: 'color', + title: '', + text: 'Correct color and lighting like a pro', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/4-PS-MakeDetailedColor.png', + }, + { + options: 'blend', + title: '', + text: 'Blend multiple shots into something new', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/5-PS-BlendImages.png', + }, + ], + }, + 'q-fallback': { + total: 6, + offset: 0, + limit: 6, + data: [ + { + options: 'photo', + title: 'Photography', + text: 'Edit or organize my photos', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/1-Photo%20ICON.svg', + image: '', + }, + { + options: 'video', + title: 'Video', + text: 'Create and edit video or audio', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/2-Video%20ICON.svg', + image: '', + }, + { + options: 'design', + title: 'Graphic design', + text: 'Design layouts or websites', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/3-Design%20ICON.svg', + image: '', + }, + { + options: 'illustration', + title: 'Illustration', + text: 'Paint, draw, or create illustrations', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/4-Illustration%20ICON.svg', + image: '', + }, + { + options: 'pdf', + title: 'PDFs', + text: 'Create, edit, or sign PDFs', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/5-PDF%20ICON.svg', + image: '', + }, + { + options: '3d', + title: '3D/AR', + text: 'Model, texture, and render 3D assets and scenes', + icon: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/6-3D-AR%20ICON.svg', + image: '', + }, + ], + }, + 'q-pdf': { + total: 6, + offset: 0, + limit: 6, + data: [ + { + options: 'create', + title: '', + text: 'Create and export PDFs to Office', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/1-Ac-CreateExport.png', + }, + { + options: 'edit', + title: '', + text: 'Edit text and images in PDFs', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/2-Ac-EditText.png', + }, + { + options: 'share', + title: '', + text: 'Share PDFs with anyone', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/3-Ac-Share.png', + }, + { + options: 'secure', + title: '', + text: 'Protect and secure PDFs', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/4-Ac-Protect.png', + }, + { + options: 'sign', + title: '', + text: 'Sign PDFs wherever you are', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/5-Ac-Sign.png', + }, + { + options: 'track', + title: '', + text: 'Track signatures and progress', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/6-Ac-TrackSignatures.png', + }, + ], + }, + 'q-design': { + total: 3, + offset: 0, + limit: 3, + data: [ + { + options: 'layouts', + title: '', + text: 'Create layouts for magazines, books, or posters', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/1-%20Id-Layouts.png', + }, + { + options: 'images', + title: '', + text: 'Combine multiple images into new designs', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/2-PS-CombineImages.png', + }, + { + options: 'graphics', + title: '', + text: 'Create graphics and designs that work at any size', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/3-Ai-CreateGraphics.png', + }, + ], + }, + 'q-illustration': { + total: 4, + offset: 0, + limit: 4, + data: [ + { + options: 'raster', + title: '', + text: 'Paint, draw, or doodle like on paper', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/1-PS-PaintDraw.png', + }, + { + options: 'vector', + title: '', + text: 'Make illustrations that work at any size', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/2-Ai-WorkAtAnySize.png', + }, + { + options: 'crisp', + title: '', + text: 'Draw crisp lines and smooth curves', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/3-Ai-CrispLines.png', + }, + { + options: 'images', + title: '', + text: 'Blend multiple images into something new', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/4-PS-BlendImages.png', + }, + ], + }, + 'q-customer': { + total: 3, + offset: 0, + limit: 3, + data: [ + { + options: 'educational', + title: '', + text: 'A student or teacher discount', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/2-StudentTeacher.png', + }, + { + options: 'business', + title: '', + text: 'Licenses and business features for teams', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/3-Work.png', + }, + { + options: 'individual', + title: '', + text: 'Neither apply', + icon: '', + image: 'https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/1-Individual.png', + }, + ], + }, + ':version': 3, + ':names': [ + 'q-video', + 'q-3d', + 'q-category', + 'questions', + 'q-rather', + 'q-photo', + 'q-fallback', + 'q-pdf', + 'q-design', + 'q-illustration', + 'q-customer', + ], + ':type': 'multi-sheet', + }, + questions: { + 'q-rather': { + total: 2, + offset: 0, + limit: 2, + data: [ + { + options: 'template', + next: 'RESET,q-customer', + 'data-analytics-title': 'ccx', + }, + { + options: 'custom', + next: 'RESULT', + 'data-analytics-title': 'Flagship', + }, + ], + }, + questions: { + total: 9, + offset: 0, + limit: 9, + data: [ + { + questions: 'q-category', + 'max-selections': '3', + 'min-selections': '1', + }, + { + questions: 'q-rather', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-video', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-photo', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-customer', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-3d', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-pdf', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-design', + 'max-selections': '1', + 'min-selections': '1', + }, + { + questions: 'q-illustration', + 'max-selections': '1', + 'min-selections': '1', + }, + ], + }, + 'q-3d': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'stage', + next: 'q-customer', + }, + { + options: 'texture', + next: 'q-customer', + }, + { + options: 'materials', + next: 'q-customer', + }, + { + options: 'model', + next: 'q-customer', + }, + { + options: 'assets', + next: 'q-customer', + }, + ], + }, + 'q-pdf': { + total: 6, + offset: 0, + limit: 6, + data: [ + { + options: 'create', + next: 'q-customer', + }, + { + options: 'edit', + next: 'q-customer', + }, + { + options: 'share', + next: 'q-customer', + }, + { + options: 'secure', + next: 'q-customer', + }, + { + options: 'sign', + next: 'q-customer', + }, + { + options: 'track', + next: 'q-customer', + }, + ], + }, + 'q-category': { + total: 22, + offset: 0, + limit: 22, + data: [ + { + options: 'fi_code', + next: '', + type: 'form', + endpoint: 'acom-prd-recom-v01', + 'api-key': 'CCHomeMLRepo1', + threshold: '0.7', + fallback: 'photoshop_cc,illustrator_cc,premierepro_cc', + 'ac-endpoint': 'autocomplete', + 'ac-scope': 'adobe_com', + 'ac-client-id': 'adobedotcom2', + }, + { + options: 'photo', + next: 'q-rather,q-photo', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'video', + next: 'q-rather,q-video', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'design', + next: 'q-rather,q-design', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'illustration', + next: 'q-rather,q-illustration', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: '3d', + next: 'NOT(q-rather),q-3d', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'pdf', + next: 'q-rather,q-pdf', + type: 'card', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'acrobat_dc_pro', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'aftereffects_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'audition_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'flash_professional_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'illustrator_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'indesign_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'lightroom_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'photoshop_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'premierepro_cc', + next: 'q-rather,q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'sbst_stager', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'sbst_painter', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'sbst_alchemist', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'sbst_shaper', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'sbst_designer', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + { + options: 'free_spark', + next: 'q-customer', + type: 'api_return_code', + endpoint: '', + 'api-key': '', + threshold: '', + fallback: '', + 'ac-endpoint': '', + 'ac-scope': '', + 'ac-client-id': '', + }, + ], + }, + 'q-customer': { + total: 3, + offset: 0, + limit: 3, + data: [ + { + options: 'educational', + next: 'RESULT', + }, + { + options: 'business', + next: 'RESULT', + }, + { + options: 'individual', + next: 'RESULT', + }, + ], + }, + 'q-video': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'social', + next: 'q-customer', + }, + { + options: 'pro', + next: 'q-customer', + }, + { + options: 'movement', + next: 'q-customer', + }, + { + options: 'animate', + next: 'q-customer', + }, + { + options: 'sound', + next: 'q-customer', + }, + ], + }, + 'q-photo': { + total: 5, + offset: 0, + limit: 5, + data: [ + { + options: 'organize', + next: 'q-customer', + }, + { + options: 'batch', + next: 'q-customer', + }, + { + options: 'edit', + next: 'q-customer', + }, + { + options: 'color', + next: 'q-customer', + }, + { + options: 'blend', + next: 'q-customer', + }, + ], + }, + 'q-design': { + total: 3, + offset: 0, + limit: 3, + data: [ + { + options: 'layouts', + next: 'q-customer', + }, + { + options: 'images', + next: 'q-customer', + }, + { + options: 'graphics', + next: 'q-customer', + }, + ], + }, + 'q-illustration': { + total: 4, + offset: 0, + limit: 4, + data: [ + { + options: 'raster', + next: 'q-customer', + }, + { + options: 'vector', + next: 'q-customer', + }, + { + options: 'crisp', + next: 'q-customer', + }, + { + options: 'images', + next: 'q-customer', + }, + ], + }, + ':version': 3, + ':names': [ + 'q-rather', + 'questions', + 'q-3d', + 'q-pdf', + 'q-category', + 'q-customer', + 'q-video', + 'q-photo', + 'q-design', + 'q-illustration', + ], + ':type': 'multi-sheet', + }, +}; + +export default resultsMock; diff --git a/test/blocks/quiz-entry/mocks/mock-states.js b/test/blocks/quiz-entry/mocks/mock-states.js new file mode 100644 index 0000000000..78c4514178 --- /dev/null +++ b/test/blocks/quiz-entry/mocks/mock-states.js @@ -0,0 +1,139 @@ +export const userSelection = [ + { + selectedQuestion: { + questions: 'q-category', + 'max-selections': '3', + 'min-selections': '1', + }, + selectedCards: { + photo: true, + video: true, + }, + }, + { + selectedQuestion: { + questions: 'q-rather', + 'max-selections': '1', + 'min-selections': '1', + }, + selectedCards: { custom: true }, + }, + { + selectedQuestion: { + questions: 'q-photo', + 'max-selections': '1', + 'min-selections': '1', + }, + selectedCards: { organize: true }, + }, + { + selectedQuestion: { + questions: 'q-video', + 'max-selections': '1', + 'min-selections': '1', + }, + selectedCards: { social: true }, + }, + { + selectedQuestion: { + questions: 'q-customer', + 'max-selections': '1', + 'min-selections': '1', + }, + selectedCards: { individual: true }, + }, +]; + +export const answers = [ + ['q-category', ['photo', 'video']], + ['q-rather', ['custom']], + ['q-photo', ['organize']], + ['q-video', ['social']], + ['q-customer', ['individual']], +]; + +export const resultRules = [ + { + result: '(ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)&(ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)', + 'umbrella-result': 'cc', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments-primary': '', + 'nested-fragments-secondary': 'marquee-product, commerce-card', + }, + { + result: '(ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)', + 'umbrella-result': '', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments-primary': 'check-bullet,marquee-plan', + 'nested-fragments-secondary': 'commerce-card', + }, + { + result: '(3d,ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)&(3d,ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)', + 'umbrella-result': '3d-umbrella', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments-primary': '', + 'nested-fragments-secondary': '', + }, + { + result: 'default', + 'umbrella-result': '', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments-primary': '', + 'nested-fragments-secondary': 'commerce-card', + }, + { + result: 'express', + 'umbrella-result': '', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments-primary': '', + 'nested-fragments-secondary': 'commerce-card', + }, +]; + +export const resultData = { + primary: [ + 'lr-ind', + 'pr-ind', + ], + secondary: [ + 'ps-ind', + 'au-ind', + ], + matchedResults: [ + { + result: '(ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)&(ai,ai-edu,ai-bus,ai-ind,au-edu,au-bus,au-ind,an-edu,an-bus,an-ind,ae-edu,ae-bus,ae-ind,lr-edu,lr-bus,lr-ind,id,pr-edu,pr-bus,pr-ind,ps-bus,ps-edu,ps-ind,ac,pdf)', + 'umbrella-result': 'cc', + url: '/path/to/result', + 'basic-fragments': 'marquee, card-list', + 'nested-fragments': 'marquee-product, commerce-card', + }, + ], +}; + +export const storedData = { + userFlow: [ + 'q-rather', + 'q-photo', + 'q-video', + 'q-design', + ], + userSelection: [ + { + selectedQuestion: { + questions: 'q-category', + 'max-selections': '3', + 'min-selections': '1', + }, + selectedCards: { + photo: true, + video: true, + design: true, + }, + }, + ], +}; diff --git a/test/blocks/quiz-entry/mocks/questions.json b/test/blocks/quiz-entry/mocks/questions.json new file mode 100644 index 0000000000..cecdffbb25 --- /dev/null +++ b/test/blocks/quiz-entry/mocks/questions.json @@ -0,0 +1,529 @@ +{ + "q-rather": { + "total": 2, + "offset": 0, + "limit": 2, + "data": [ + { + "options": "template", + "next": "RESET,q-customer", + "data-analytics-title": "ccx" + }, + { + "options": "custom", + "next": "RESULT", + "data-analytics-title": "Flagship" + } + ] + }, + "questions": { + "total": 9, + "offset": 0, + "limit": 9, + "data": [ + { + "questions": "q-category", + "max-selections": "3", + "min-selections": "1" + }, + { + "questions": "q-rather", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-video", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-photo", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-customer", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-3d", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-pdf", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-design", + "max-selections": "1", + "min-selections": "1" + }, + { + "questions": "q-illustration", + "max-selections": "1", + "min-selections": "1" + } + ] + }, + "q-3d": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "stage", + "next": "q-customer" + }, + { + "options": "texture", + "next": "q-customer" + }, + { + "options": "materials", + "next": "q-customer" + }, + { + "options": "model", + "next": "q-customer" + }, + { + "options": "assets", + "next": "q-customer" + } + ] + }, + "q-pdf": { + "total": 6, + "offset": 0, + "limit": 6, + "data": [ + { + "options": "create", + "next": "q-customer" + }, + { + "options": "edit", + "next": "q-customer" + }, + { + "options": "share", + "next": "q-customer" + }, + { + "options": "secure", + "next": "q-customer" + }, + { + "options": "sign", + "next": "q-customer" + }, + { + "options": "track", + "next": "q-customer" + } + ] + }, + "q-category": { + "total": 22, + "offset": 0, + "limit": 22, + "data": [ + { + "options": "fi_code", + "next": "", + "type": "form", + "endpoint": "acom-prd-recom-v01", + "api-key": "CCHomeMLRepo1", + "threshold": "0.7", + "fallback": "photoshop_cc,illustrator_cc,premierepro_cc", + "ac-endpoint": "autocomplete", + "ac-scope": "adobe_com", + "ac-client-id": "adobedotcom2" + }, + { + "options": "photo", + "next": "q-rather,q-photo", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "video", + "next": "q-rather,q-video", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "design", + "next": "q-rather,q-design", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "illustration", + "next": "q-rather,q-illustration", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "3d", + "next": "NOT(q-rather),q-3d", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "pdf", + "next": "q-rather,q-pdf", + "type": "card", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "acrobat_dc_pro", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "aftereffects_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "audition_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "flash_professional_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "illustrator_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "indesign_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "lightroom_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "photoshop_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "premierepro_cc", + "next": "q-rather,q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "sbst_stager", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "sbst_painter", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "sbst_alchemist", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "sbst_shaper", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "sbst_designer", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + }, + { + "options": "free_spark", + "next": "q-customer", + "type": "api_return_code", + "endpoint": "", + "api-key": "", + "threshold": "", + "fallback": "", + "ac-endpoint": "", + "ac-scope": "", + "ac-client-id": "" + } + ] + }, + "q-customer": { + "total": 3, + "offset": 0, + "limit": 3, + "data": [ + { + "options": "educational", + "next": "RESULT" + }, + { + "options": "business", + "next": "RESULT" + }, + { + "options": "individual", + "next": "RESULT" + } + ] + }, + "q-video": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "social", + "next": "q-customer" + }, + { + "options": "pro", + "next": "q-customer" + }, + { + "options": "movement", + "next": "q-customer" + }, + { + "options": "animate", + "next": "q-customer" + }, + { + "options": "sound", + "next": "q-customer" + } + ] + }, + "q-photo": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "organize", + "next": "q-customer" + }, + { + "options": "batch", + "next": "q-customer" + }, + { + "options": "edit", + "next": "q-customer" + }, + { + "options": "color", + "next": "q-customer" + }, + { + "options": "blend", + "next": "q-customer" + } + ] + }, + "q-design": { + "total": 3, + "offset": 0, + "limit": 3, + "data": [ + { + "options": "layouts", + "next": "q-customer" + }, + { + "options": "images", + "next": "q-customer" + }, + { + "options": "graphics", + "next": "q-customer" + } + ] + }, + "q-illustration": { + "total": 4, + "offset": 0, + "limit": 4, + "data": [ + { + "options": "raster", + "next": "q-customer" + }, + { + "options": "vector", + "next": "q-customer" + }, + { + "options": "crisp", + "next": "q-customer" + }, + { + "options": "images", + "next": "q-customer" + } + ] + }, + ":version": 3, + ":names": [ + "q-rather", + "questions", + "q-3d", + "q-pdf", + "q-category", + "q-customer", + "q-video", + "q-photo", + "q-design", + "q-illustration" + ], + ":type": "multi-sheet" +} diff --git a/test/blocks/quiz-entry/mocks/quiz.html b/test/blocks/quiz-entry/mocks/quiz.html new file mode 100644 index 0000000000..3c0aead1ad --- /dev/null +++ b/test/blocks/quiz-entry/mocks/quiz.html @@ -0,0 +1,24 @@ +
+
+
+
data
+
/drafts/colloyd/quiz-entry/
+
+
+
quiz
+
/drafts/colloyd/quiz/
+
+
+
max-questions
+
1
+
+
+
analytics-type
+
cc:app-reco
+
+
+
analytics-quiz
+
UARv4
+
+
+
diff --git a/test/blocks/quiz-entry/mocks/result-resources.json b/test/blocks/quiz-entry/mocks/result-resources.json new file mode 100644 index 0000000000..cc6929189c --- /dev/null +++ b/test/blocks/quiz-entry/mocks/result-resources.json @@ -0,0 +1,207 @@ +{ + "total": 25, + "offset": 0, + "limit": 25, + "data": [ + { + "product": "ps-edu", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "ps-bus", + "marquee": "/path/to/marquee", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "ps-ind", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "lr-edu", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "lr-bus", + "marquee": "/path/to/marquee", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "lr-ind", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "pr-edu", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "pr-bus", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "pr-ind", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "ae", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "an", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "/fragments/card/animate", + "marquee-product": "", + "page": "" + }, + { + "product": "au", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "id", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "ai", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "acrobat-pro", + "marquee": "/fragments/marquee/acrobat", + "card-list": "", + "commerce-card": "/fragments/card/acrobat", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-collection", + "marquee": "/fragments/marquee/subtance-3d", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-stager", + "marquee": "/fragments/marquee/subtance-3d-stager", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-painter", + "marquee": "/fragments/marquee/subtance-3d-painter", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-sampler", + "marquee": "/fragments/marquee/subtance-3d-sampler", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-modeler", + "marquee": "/fragments/marquee/subtance-3d-modeler", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "substance-3d-designer", + "marquee": "/fragments/marquee/subtance-3d-designer", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "express", + "marquee": "/path/to/marquee", + "card-list": "", + "commerce-card": "path-to-commerce-card", + "marquee-product": "", + "page": "" + }, + { + "product": "cc", + "marquee": "/path/to/marquee", + "card-list": "/path/to/cardlist", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "ac", + "marquee": "", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + }, + { + "product": "3d-umbrella", + "marquee": "", + "card-list": "", + "commerce-card": "", + "marquee-product": "", + "page": "" + } + ] +} diff --git a/test/blocks/quiz-entry/mocks/strings.json b/test/blocks/quiz-entry/mocks/strings.json new file mode 100644 index 0000000000..4b6b7635cc --- /dev/null +++ b/test/blocks/quiz-entry/mocks/strings.json @@ -0,0 +1,506 @@ +{ + "q-video": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "social", + "title": "", + "text": "Create, edit, and share on social", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/1-PR-CreateEditShare.png" + }, + { + "options": "pro", + "title": "", + "text": "Make pro-level edits for high-quality results", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/2-PR-ProLevelEdits.png" + }, + { + "options": "movement", + "title": "", + "text": "Create graphics and transitions that move", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/3-AE-TitlesAndTransitions.png" + }, + { + "options": "animate", + "title": "", + "text": "Make animations for cartoons or games", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/4-AN-Animations.png" + }, + { + "options": "sound", + "title": "", + "text": "Edit, mix, and add sound effects", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-video/5-AU-SoundEffects.png" + } + ] + }, + "q-3d": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "stage", + "title": "", + "text": "Assemble, stage, and render 3D scenes", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/3-Stager@1x.png" + }, + { + "options": "texture", + "title": "", + "text": "Texture 3D assets in real time", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/2-Painter@1x.png" + }, + { + "options": "materials", + "title": "", + "text": "Create 3D materials from real-life images", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/5-Sampler@1x.png" + }, + { + "options": "model", + "title": "", + "text": "Create 3D models with digital clay", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/1-Modeler@1x.png" + }, + { + "options": "assets", + "title": "", + "text": "Design 3D assets and materials", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q3/4-Designer@1x.png" + } + ] + }, + "q-category": { + "total": 7, + "offset": 0, + "limit": 7, + "data": [ + { + "options": "fi_code", + "title": "Describe your interest here", + "text": "Ask our AI assistant", + "icon": "https://milo.adobe.com/drafts/quiz/quiz-ai/search.svg", + "image": "" + }, + { + "options": "photo", + "title": "Photography", + "text": "Edit or organize my photos", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/photography.png" + }, + { + "options": "video", + "title": "Video", + "text": "Create and edit video or audio", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/video.png" + }, + { + "options": "design", + "title": "Graphic design", + "text": "Design layouts or websites", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/design.png" + }, + { + "options": "illustration", + "title": "Illustration", + "text": "Paint, draw, or create illustrations", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/illustration.png" + }, + { + "options": "pdf", + "title": "PDFs", + "text": "Create, edit, or sign PDFs", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/pdf.png" + }, + { + "options": "3d", + "title": "3D/AR", + "text": "Model, texture, and render 3D assets and scenes", + "icon": "", + "image": "https://main--milo--adobecom.hlx.page/drafts/colloyd/quiz-entry/images/3dar.png" + } + ] + }, + "questions": { + "total": 10, + "offset": 0, + "limit": 10, + "data": [ + { + "q": "q-category", + "heading": "Not sure which apps are best for you?", + "sub-head": "Tell us what you’re interested in. We’ll help you figure it out.", + "btn": "Continue", + "text": "Or pick up to 3 below", + "background": "https://milo.adobe.com/drafts/quiz/quiz-2/quiz-background.jpeg", + "footerFragment": "" + }, + { + "q": "q-fallback", + "heading": "We're sorry our assistant couldn't help today.", + "sub-head": "Please choose up to three options.", + "btn": "Next", + "text": "", + "background": "https://milo.adobe.com/drafts/quiz/quiz-2/quiz-background.jpeg", + "footerFragment": "" + }, + { + "q": "q-photo", + "heading": "What do you want to do with photos?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Photo%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "https://milo.adobe.com/fragments/quiz/sample-uar-fragments/footer/footer1" + }, + { + "q": "q-video", + "heading": "What do you want to do with video?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Photo%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-design", + "heading": "What do you want to do with design?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Design%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-illustration", + "heading": "What do you want to do with illustration?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Illustration%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-pdf", + "heading": "What do you want to do with PDFs?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q2-Acrobat%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-3d", + "heading": "What do you want to do with 3D/AR?", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-3D-AR%20BKGD?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-rather", + "heading": "For your projects, would you rather:", + "sub-head": "Pick one.", + "btn": "Next", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q3-Learn%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "" + }, + { + "q": "q-customer", + "heading": "What else are you looking for today?", + "sub-head": "Pick one.", + "btn": "Get your results", + "text": "", + "background": "https://cc-prod.scene7.com/is/image/CCProdAuthor/DSK-Q4%20BKGD%202X?$pjpeg$&jpegSize=300&wid=1920", + "footerFragment": "https://milo.adobe.com/fragments/quiz/sample-uar-fragments/footer/footer2" + } + ] + }, + "q-rather": { + "total": 2, + "offset": 0, + "limit": 2, + "data": [ + { + "options": "template", + "title": "", + "text": "Edit quickly and customize templates", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/1-Templates.png" + }, + { + "options": "custom", + "title": "", + "text": "Take the time to control every detail", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/2-CustomDesigns.png" + } + ] + }, + "q-photo": { + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "options": "organize", + "title": "", + "text": "Get them sorted and organized", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/1-LR-StoreAndOrganize.png" + }, + { + "options": "batch", + "title": "", + "text": "Edit lots of photos quickly", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/2-LR-ApplyFilters.png" + }, + { + "options": "edit", + "title": "", + "text": "Edit and finesse the smallest details", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/3-PS-RemoveObjects.png" + }, + { + "options": "color", + "title": "", + "text": "Correct color and lighting like a pro", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/4-PS-MakeDetailedColor.png" + }, + { + "options": "blend", + "title": "", + "text": "Blend multiple shots into something new", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-photo/5-PS-BlendImages.png" + } + ] + }, + "q-fallback": { + "total": 6, + "offset": 0, + "limit": 6, + "data": [ + { + "options": "photo", + "title": "Photography", + "text": "Edit or organize my photos", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/1-Photo%20ICON.svg", + "image": "" + }, + { + "options": "video", + "title": "Video", + "text": "Create and edit video or audio", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/2-Video%20ICON.svg", + "image": "" + }, + { + "options": "design", + "title": "Graphic design", + "text": "Design layouts or websites", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/3-Design%20ICON.svg", + "image": "" + }, + { + "options": "illustration", + "title": "Illustration", + "text": "Paint, draw, or create illustrations", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/4-Illustration%20ICON.svg", + "image": "" + }, + { + "options": "pdf", + "title": "PDFs", + "text": "Create, edit, or sign PDFs", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/5-PDF%20ICON.svg", + "image": "" + }, + { + "options": "3d", + "title": "3D/AR", + "text": "Model, texture, and render 3D assets and scenes", + "icon": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/6-3D-AR%20ICON.svg", + "image": "" + } + ] + }, + "q-pdf": { + "total": 6, + "offset": 0, + "limit": 6, + "data": [ + { + "options": "create", + "title": "", + "text": "Create and export PDFs to Office", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/1-Ac-CreateExport.png" + }, + { + "options": "edit", + "title": "", + "text": "Edit text and images in PDFs", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/2-Ac-EditText.png" + }, + { + "options": "share", + "title": "", + "text": "Share PDFs with anyone", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/3-Ac-Share.png" + }, + { + "options": "secure", + "title": "", + "text": "Protect and secure PDFs", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/4-Ac-Protect.png" + }, + { + "options": "sign", + "title": "", + "text": "Sign PDFs wherever you are", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/5-Ac-Sign.png" + }, + { + "options": "track", + "title": "", + "text": "Track signatures and progress", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-pdf/6-Ac-TrackSignatures.png" + } + ] + }, + "q-design": { + "total": 3, + "offset": 0, + "limit": 3, + "data": [ + { + "options": "layouts", + "title": "", + "text": "Create layouts for magazines, books, or posters", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/1-%20Id-Layouts.png" + }, + { + "options": "images", + "title": "", + "text": "Combine multiple images into new designs", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/2-PS-CombineImages.png" + }, + { + "options": "graphics", + "title": "", + "text": "Create graphics and designs that work at any size", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-design/3-Ai-CreateGraphics.png" + } + ] + }, + "q-illustration": { + "total": 4, + "offset": 0, + "limit": 4, + "data": [ + { + "options": "raster", + "title": "", + "text": "Paint, draw, or doodle like on paper", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/1-PS-PaintDraw.png" + }, + { + "options": "vector", + "title": "", + "text": "Make illustrations that work at any size", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/2-Ai-WorkAtAnySize.png" + }, + { + "options": "crisp", + "title": "", + "text": "Draw crisp lines and smooth curves", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/3-Ai-CrispLines.png" + }, + { + "options": "images", + "title": "", + "text": "Blend multiple images into something new", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q2-illustration/4-PS-BlendImages.png" + } + ] + }, + "q-customer": { + "total": 3, + "offset": 0, + "limit": 3, + "data": [ + { + "options": "educational", + "title": "", + "text": "A student or teacher discount", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/2-StudentTeacher.png" + }, + { + "options": "business", + "title": "", + "text": "Licenses and business features for teams", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/3-Work.png" + }, + { + "options": "individual", + "title": "", + "text": "Neither apply", + "icon": "", + "image": "https://www.adobe.com/content/dam/cc/Images/app-recommender/multi-select/quiz-question-card-thumbnails/q4/1-Individual.png" + } + ] + }, + ":version": 3, + ":names": [ + "q-video", + "q-3d", + "q-category", + "questions", + "q-rather", + "q-photo", + "q-fallback", + "q-pdf", + "q-design", + "q-illustration", + "q-customer" + ], + ":type": "multi-sheet" +} diff --git a/test/blocks/quiz-entry/quiz-entry.test.js b/test/blocks/quiz-entry/quiz-entry.test.js new file mode 100644 index 0000000000..993ee21594 --- /dev/null +++ b/test/blocks/quiz-entry/quiz-entry.test.js @@ -0,0 +1,159 @@ +/* eslint-disable no-promise-executor-return */ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; +import sinon from 'sinon'; +import init from '../../../libs/blocks/quiz-entry/quiz-entry.js'; +import { getSuggestions } from '../../../libs/blocks/quiz-entry/quizPopover.js'; // Correct the path as needed + +let fetchStub; +let quizEntryElement; +const { default: mockData } = await import('./mocks/mock-data.js'); +const mockQuestionsData = mockData.questions; +const mockStringsData = mockData.strings; +const quizConfig = { + quizPath: '/drafts/quiz/quiz-entry/', + maxQuestions: 1, + analyticsQuiz: 'clientv1', + analyticsType: 'cc:app-test', + questionData: mockQuestionsData, + stringsData: mockStringsData, +}; + +describe('Quiz Entry Component', () => { + beforeEach(async () => { + window.lana = { log: sinon.stub() }; + fetchStub = sinon.stub(window, 'fetch'); + fetchStub.resolves({ + ok: true, + json: () => Promise.resolve({ suggested_completions: ['designer desk', 'design logos'] }), + }); + document.body.innerHTML = await readFile({ path: './mocks/index.html' }); + quizEntryElement = document.querySelector('.quiz-entry'); + await init(quizEntryElement, quizConfig); + await new Promise((resolve) => setTimeout(resolve, 100)); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should trigger onMLInput and update suggestions', async () => { + const mlInputField = document.querySelector('#quiz-input'); + const testInput = 'design'; + const inputEvent = new Event('input', { bubbles: true }); + mlInputField.value = testInput; + mlInputField.dispatchEvent(inputEvent); + await new Promise((resolve) => setTimeout(resolve, 100)); + const popoverContainer = document.querySelector('.popover-container'); + const suggestionItems = popoverContainer.querySelectorAll('.popover-item'); + expect(suggestionItems).to.exist; + }); + + it('Should trigger popover content on click', async () => { + const mlInputField = document.querySelector('#quiz-input'); + const testInput = 'design'; + const inputEvent = new Event('input', { bubbles: true }); + mlInputField.value = testInput; + mlInputField.dispatchEvent(inputEvent); + await new Promise((resolve) => setTimeout(resolve, 100)); + const popoverItem = document.querySelector('.popover-item'); + popoverItem.innerHTML = 'design a logo'; + popoverItem.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + const enterKeyEvent = new KeyboardEvent('keypress', { + key: 'Enter', + code: 'Enter', + keyCode: 13, + }); + mlInputField.dispatchEvent(enterKeyEvent); + await new Promise((resolve) => setTimeout(resolve, 100)); + mlInputField.value = 'design a logo'; + expect(mlInputField.value).to.equal('design a logo'); + }); + + it('should fetch suggestions and return data on successful response', async () => { + const mockApiResponse = { + ok: true, + json: () => Promise.resolve({ suggested_completions: ['suggestion1', 'suggestion2'] }), + }; + fetchStub.resolves(mockApiResponse); + const result = await getSuggestions('test-endpoint', 'test-client-id', 'query', 'test-scope'); + expect(fetchStub.calledOnce).to.be.true; + expect(result).to.deep.equal({ suggested_completions: ['suggestion1', 'suggestion2'] }); + const expectedUrl = 'https://adobesearch.adobe.io/test-endpoint/completions?q[text]=query&q[locale]=en_us&scope=test-scope'; + expect(fetchStub.calledWith(expectedUrl, { + method: 'GET', + headers: { 'x-api-key': 'test-client-id' }, + })).to.be.true; + }); + + it('should handle failed fetch attempts', async () => { + fetchStub.resolves({ ok: false }); + const result = await getSuggestions('test-endpoint', 'test-client-id', 'query', 'test-scope'); + expect(fetchStub.calledOnce).to.be.true; + expect(result).to.equal(''); + }); + + it('should initialize with provided element and display the quiz', async () => { + expect(quizEntryElement.innerHTML).to.include('quiz-container'); + }); + + it('should handle user interaction and update selection state', async () => { + const option = quizEntryElement.querySelector('.quiz-option'); + option.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(option.classList.contains('selected')).to.be.true; + }); + + it('1 should trigger continueQuiz on enter key press', async () => { + const mlFieldInput = document.querySelector('#quiz-input'); + const enterKeyEvent = new KeyboardEvent('keypress', { + key: 'Enter', + code: 'Enter', + keyCode: 13, + }); + mlFieldInput.dispatchEvent(enterKeyEvent); + }); + + it('should clear the input field on clear button click', async () => { + const mlFieldInput = document.querySelector('#quiz-input'); + const clearButton = document.querySelector('#quiz-input-clear'); + mlFieldInput.value = 'test'; + clearButton.click(); + expect(mlFieldInput.value).to.equal(''); + }); + it('should have an input focus() on suggestion click', async () => { + const mlFieldInput = document.querySelector('#quiz-input'); + mlFieldInput.value = 'design a logo'; + const inputEvent = new Event('input', { bubbles: true }); + mlFieldInput.dispatchEvent(inputEvent); + await new Promise((resolve) => setTimeout(resolve, 100)); + const suggestionItem = document.querySelector('.popover-item'); + suggestionItem.click(); + expect(mlFieldInput).to.equal(document.activeElement); + }); + it('should have the selected class after clicking on an option', async () => { + const option = document.querySelector('.quiz-option'); + option.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(option.classList.contains('selected')).to.be.true; + }); + it('should remove the selected class after clicking on the .quiz-option element again', async () => { + const option = document.querySelector('.quiz-option'); + option.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + option.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(option.classList.contains('selected')).to.be.false; + }); + it('continue should be available after mlfield is used', async () => { + const mlFieldInput = document.querySelector('#quiz-input'); + const continueButton = document.querySelector('.quiz-button'); + mlFieldInput.value = 'design a logo'; + const inputEvent = new Event('input', { bubbles: true }); + mlFieldInput.dispatchEvent(inputEvent); + continueButton.click(); + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(continueButton.classList.contains('disabled')).to.be.false; + }); +}); From e1e2ddc4858681c16e38fff1ccd50deb3a250226 Mon Sep 17 00:00:00 2001 From: Elan Bartholomew Date: Tue, 14 May 2024 11:05:30 -0600 Subject: [PATCH 12/14] update tests again --- libs/blocks/form/form.js | 1 + test/blocks/form/form.test.js | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/blocks/form/form.js b/libs/blocks/form/form.js index d6fb180147..cfa871dca3 100644 --- a/libs/blocks/form/form.js +++ b/libs/blocks/form/form.js @@ -88,6 +88,7 @@ function createButton({ type, label }, thankYou) { button.addEventListener('click', async (event) => { const form = button.closest('form'); if (form.checkValidity()) { + form.setAttribute('submitted', 'true'); event.preventDefault(); button.setAttribute('disabled', ''); const submission = await submitForm(form); diff --git a/test/blocks/form/form.test.js b/test/blocks/form/form.test.js index 8a2318450b..a937af3c16 100644 --- a/test/blocks/form/form.test.js +++ b/test/blocks/form/form.test.js @@ -94,8 +94,7 @@ describe('Form Block', async () => { const form = await waitForElement('form'); form.querySelector('.form-submit-wrapper button').dispatchEvent(new Event('click')); await new Promise((resolve) => { setTimeout(() => resolve(), 150); }); - const thanks = document.querySelector('.thank-you'); - expect(thanks).to.exist; + expect(form.getAttribute('submitted')).to.equal('true'); }); it('clears successfully', async () => { From 04a53a658d8557fa354f7101351423dc8ad0ac14 Mon Sep 17 00:00:00 2001 From: Elan Bartholomew Date: Tue, 14 May 2024 11:15:15 -0600 Subject: [PATCH 13/14] consolidate args to config obj --- libs/blocks/form/form.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/blocks/form/form.js b/libs/blocks/form/form.js index cfa871dca3..657a7255e0 100644 --- a/libs/blocks/form/form.js +++ b/libs/blocks/form/form.js @@ -233,7 +233,7 @@ function lowercaseKeys(obj) { }, {}); } -async function createForm(formURL, thankYou, formData, endpoint = '') { +async function createForm({ formURL, thankYou, formData, endpoint }) { const { pathname } = new URL(formURL); let json = formData; /* c8 ignore next 4 */ @@ -294,6 +294,7 @@ export default async function decorate(block, formData = null) { const [form, endpoint] = block.querySelectorAll(':scope > div:first-child a'); const thankYou = block.querySelector(':scope > div:last-of-type > div'); thankYou.remove(); + const config = { formURL: form?.href, thankYou, formData, endpoint: endpoint?.href }; if (endpoint) endpoint.parentElement.remove(); - if (form) form.replaceWith(await createForm(form.href, thankYou, formData, endpoint?.href)); + if (form) form.replaceWith(await createForm(config)); } From 22416384301627dbd37e27e50065ace3a04e8abd Mon Sep 17 00:00:00 2001 From: Elan Bartholomew <79870969+elan-tbx@users.noreply.github.com> Date: Tue, 28 May 2024 17:07:32 -0600 Subject: [PATCH 14/14] add empty default for createForm Co-authored-by: Rares Munteanu --- libs/blocks/form/form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/blocks/form/form.js b/libs/blocks/form/form.js index 657a7255e0..1a3ebc0733 100644 --- a/libs/blocks/form/form.js +++ b/libs/blocks/form/form.js @@ -233,7 +233,7 @@ function lowercaseKeys(obj) { }, {}); } -async function createForm({ formURL, thankYou, formData, endpoint }) { +async function createForm({ formURL, thankYou, formData, endpoint } = {}) { const { pathname } = new URL(formURL); let json = formData; /* c8 ignore next 4 */