diff --git a/acrobat/blocks/verb-widget/icons.js b/acrobat/blocks/verb-widget/icons.js index bf90dfc1..460dbbb7 100644 --- a/acrobat/blocks/verb-widget/icons.js +++ b/acrobat/blocks/verb-widget/icons.js @@ -4,6 +4,7 @@ const ICONS = { WIDGET_ICON: '', fillsign: '', + 'compress-pdf': '', UPLOAD_ICON: '', SECURITY_ICON: '', INFO_ICON: '', diff --git a/acrobat/blocks/verb-widget/limits.js b/acrobat/blocks/verb-widget/limits.js index 4457b30b..f9436f94 100644 --- a/acrobat/blocks/verb-widget/limits.js +++ b/acrobat/blocks/verb-widget/limits.js @@ -1,25 +1,37 @@ const LIMITS = { fillsign: { - maxFileSize: 100000000, // 100 MB + maxFileSize: 104857600, // 100 MB maxFileSizeFriendly: '100 MB', // 100 MB - acceptedFiles: '.pdf', + acceptedFiles: ['application/pdf'], maxNumFiles: 1, + multipleFiles: false, mobileApp: true, }, 'delete-pages': { maxFileSize: 100000000, // 1 MB - acceptedFiles: '.pdf', + acceptedFiles: ['application/pdf'], maxNumFiles: 1, }, 'number-pages': { maxFileSize: 100000000, // 1 MB - acceptedFiles: '.pdf', + acceptedFiles: ['application/pdf'], maxNumFiles: 1, }, 'compress-pdf': { - maxFileSize: 100000000, - acceptedFiles: '.pdf', - maxNumFiles: 1, + maxFileSize: 2147483648, + maxFileSizeFriendly: '2 GB', + acceptedFiles: [ + 'application/pdf', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.ms-powerpoint', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'image/jpeg', + 'image/png', + ], + multipleFiles: true, }, }; diff --git a/acrobat/blocks/verb-widget/verb-widget.js b/acrobat/blocks/verb-widget/verb-widget.js index 9a36104a..1ccf9104 100644 --- a/acrobat/blocks/verb-widget/verb-widget.js +++ b/acrobat/blocks/verb-widget/verb-widget.js @@ -133,7 +133,14 @@ export default async function init(element) { } const widgetMobileButton = createTag('a', { class: 'verb-mobile-cta', href: mobileLink }, window.mph['verb-widget-cta-mobile']); - const button = createTag('input', { type: 'file', accept: LIMITS[VERB].acceptedFiles, id: 'file-upload', class: 'hide', 'aria-hidden': true }); + const button = createTag('input', { + type: 'file', + accept: LIMITS[VERB]?.acceptedFiles, + id: 'file-upload', + class: 'hide', + 'aria-hidden': true, + ...(LIMITS[VERB]?.multipleFiles && { multiple: '' }), + }); const widgetImage = createTag('div', { class: 'verb-image' }); const verbIconName = `${VERB}`; const verbImageSvg = createSvgElement(verbIconName); diff --git a/package-lock.json b/package-lock.json index 929bcedd..f7b27588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@amwp/platform-ui-automation": "^0.0.6", - "@amwp/platform-ui-lib-adobe": "^0.0.7", + "@amwp/platform-ui-lib-adobe": "^0.0.9", "@babel/core": "7.23.2", "@babel/eslint-parser": "7.22.15", "@babel/register": "7.22.15", @@ -119,9 +119,9 @@ } }, "node_modules/@amwp/platform-ui-lib-adobe": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@amwp/platform-ui-lib-adobe/-/platform-ui-lib-adobe-0.0.7.tgz", - "integrity": "sha512-5tF6QFLZIvGDS/thYanj2srt6NrSQ0lq34m9KzaPEIVfj2OywLLVoavDaxgJvmhTGywIGngMrXyDx+YIUIInyA==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@amwp/platform-ui-lib-adobe/-/platform-ui-lib-adobe-0.0.9.tgz", + "integrity": "sha512-F/1En1XlUJMYxbpesvd0G64XDyO8xsLUGIyyoBs4YehcDVk7CbHRHVShs6U9LoQ7A4ElEb5KXK7W5YqtRWp+nw==", "dev": true }, "node_modules/@babel/code-frame": { diff --git a/package.json b/package.json index 3b3bd3c9..f4ce8a6e 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "homepage": "https://github.com/adobecom/dc#readme", "devDependencies": { "@amwp/platform-ui-automation": "^0.0.6", - "@amwp/platform-ui-lib-adobe": "^0.0.7", + "@amwp/platform-ui-lib-adobe": "^0.0.9", "@babel/core": "7.23.2", "@babel/eslint-parser": "7.22.15", "@babel/register": "7.22.15", diff --git a/test/e2e/features/unity/verbs.feature b/test/e2e/features/unity/verbs.feature new file mode 100644 index 00000000..2e5db0ce --- /dev/null +++ b/test/e2e/features/unity/verbs.feature @@ -0,0 +1,26 @@ +Feature: Frictionless Converter Block + + Background: + Given I have a new browser context + + @smoke @unity @sign-pdf @choosefile + Scenario Outline: L1 Verb - Upload and sign-in + Given I go to the page + Then I choose the file "" to upload + Then I wait for 5 seconds + Then I should see the address bar contains "acrobat.adobe.com" + + Examples: + | Verb | File | + | sign-pdf | test-files/test.pdf | + + @smoke @unity @sign-pdf @dragndrop + Scenario Outline: L1 Verb - Upload and sign-in + Given I go to the page + Then I drag-and-drop the file "" to upload + Then I wait for 5 seconds + Then I should see the address bar contains "acrobat.adobe.com" + + Examples: + | Verb | File | + | sign-pdf | test-files/test.pdf | \ No newline at end of file diff --git a/test/e2e/page-objects/unity.page.js b/test/e2e/page-objects/unity.page.js new file mode 100644 index 00000000..31ebbe71 --- /dev/null +++ b/test/e2e/page-objects/unity.page.js @@ -0,0 +1,34 @@ +import { classes } from "polytype"; +import { DcGnavPage } from "./dcgnav.page"; +import { CaaSSection } from "./caas.section"; +import { VerbWidgetSection } from "./verbwidget.section"; + +export class UnityPage extends classes(DcGnavPage, VerbWidgetSection, CaaSSection) { + constructor(contentPath) { + super({ + super: DcGnavPage, + arguments: [contentPath], + }); + this.buildProps({ + howToDefault: 'div[data-path*="how-to/default"]', + howTo2ndConversion: '[data-tag="2nd conversion"] div[data-path*="how-to/2nd-conversion"]', + verbSubfooter: '.verb-subfooter', + reviewComponent: '.review', + reviewStats: '.hlx-ReviewStats', + reviewSubmitResponse: '.hlx-submitResponse', + reviewDisabled: '.hlx-Review-ratingFields[disabled]', + reviewCommentField: '.hlx-Review-commentFields textarea', + reviewCommentSubmit: '.hlx-Review-commentFields input[type="submit"]', + reviewInputField: 'fieldset.hlx-Review-ratingFields input', + signUp: '[href*="https://auth.services.adobe.com"][href*="signup"]', + extensionModal: '#chromeext, #edgeext', + closeExtensionModal: '#chromeext .dialog-close, #edgeext .dialog-close', + eventwrapperOnload: '.eventwrapper.onload', + previewDescription: 'div[class*="previewDescription"]', + }); + } + + reviewStartInput(rating) { + return this.native.locator(`.hlx-Review-ratingFields input[value="${rating}"]`); + } +} diff --git a/test/e2e/page-objects/verbwidget.section.js b/test/e2e/page-objects/verbwidget.section.js new file mode 100644 index 00000000..8cfeee3f --- /dev/null +++ b/test/e2e/page-objects/verbwidget.section.js @@ -0,0 +1,69 @@ +import fs from 'fs'; +import path from 'path'; +import { Section } from '@amwp/platform-ui-automation/lib/common/page-objects/section'; + +export class VerbWidgetSection extends Section { + constructor() { + super(); + this.buildProps({ + selectButton: '.verb-cta', + fileUploadInput: '#file-upload', + dropZone: '#drop-zone', + }) + } + + async chooseFiles(filePaths) { + const fileChooserPromise = this.native.waitForEvent('filechooser'); + this.selectButton.click(); + const fileChooser = await fileChooserPromise; + await fileChooser.setFiles(filePaths); + } + + async dragndropFiles(filePaths) { + const filePath = filePaths[0]; + const buffer = fs.readFileSync(filePath).toString('base64'); + const basename = path.basename(filePath); + + const dataTransfer = await this.dropZone.evaluateHandle(async({bufferData, basename}) => { + const dt = new DataTransfer(); + const blobData = await fetch(bufferData).then((res) => res.blob()); + const file = new File([blobData], basename, { type: 'application/pdf' }); + dt.items.add(file); + return dt; + }, { + bufferData: `data:application/octet-stream;base64,${buffer}`, + basename + }); + + await this.dropZone.dispatchEvent('drop', { dataTransfer }); + } +} + +async function dragAndDropFile( + page, + selector, + filePath, + fileName, + fileType = '' + ) { + const buffer = readFileSync(filePath).toString('base64'); + + const dataTransfer = await page.evaluateHandle( + async ({ bufferData, localFileName, localFileType }) => { + const dt = new DataTransfer(); + + const blobData = await fetch(bufferData).then((res) => res.blob()); + + const file = new File([blobData], localFileName, { type: localFileType }); + dt.items.add(file); + return dt; + }, + { + bufferData: `data:application/octet-stream;base64,${buffer}`, + localFileName: fileName, + localFileType: fileType, + } + ); + + await page.dispatchEvent(selector, 'drop', { dataTransfer }); + }; \ No newline at end of file diff --git a/test/e2e/step-definitions/dc.steps.js b/test/e2e/step-definitions/dc.steps.js index a42ac101..8fe20c8e 100644 --- a/test/e2e/step-definitions/dc.steps.js +++ b/test/e2e/step-definitions/dc.steps.js @@ -23,6 +23,7 @@ import { MergePdfPage } from "../page-objects/mergepdf.page"; import { CompressPdfPage } from "../page-objects/compresspdf.page"; import { PasswordProtectPdfPage } from "../page-objects/passwordprotectpdf.page"; import { FrictionlessPage } from "../page-objects/frictionless.page"; +import { UnityPage } from "../page-objects/unity.page"; import { DCPage } from "../page-objects/dc.page"; import { cardinal } from "../support/cardinal"; import { expect } from "@playwright/test"; @@ -643,3 +644,45 @@ Then(/^I confirm phone number is different and has geo-ip value "([^"]*)"$/, asy expect(this.phoneNumber).not.toEqual(geoIpPhoneNumber); expect(geoIpPhoneNumber).toEqual(geoIpPhoneNumberValue); }) + +Then(/^I choose the (?:PDF|file|files) "([^\"]*)" to upload$/, async function (filePath) { + this.context(UnityPage); + const filePaths = filePath.split(","); + const absPaths = filePaths.map((x) => + path.resolve(global.config.profile.site, x) + ); + let retry = 3; + while (retry > 0) { + await expect(this.page.selectButton).toHaveCount(1, { timeout: 15000 }); + await this.page.native.waitForTimeout(2000); + try { + await this.page.chooseFiles(absPaths); + await this.page.native.waitForTimeout(2000); + await expect(this.page.selectButton).toHaveCount(0, { timeout: 15000 }); + retry = 0; + } catch { + retry--; + } + } +}); + +Then(/^I drag-and-drop the (?:PDF|file|files) "([^\"]*)" to upload$/, async function (filePath) { + this.context(UnityPage); + const filePaths = filePath.split(","); + const absPaths = filePaths.map((x) => + path.resolve(global.config.profile.site, x) + ); + let retry = 3; + while (retry > 0) { + await expect(this.page.selectButton).toHaveCount(1, { timeout: 15000 }); + await this.page.native.waitForTimeout(2000); + try { + await this.page.dragndropFiles(absPaths); + await this.page.native.waitForTimeout(2000); + await expect(this.page.selectButton).toHaveCount(0, { timeout: 15000 }); + retry = 0; + } catch { + retry--; + } + } +}); \ No newline at end of file