Skip to content

Commit f767d52

Browse files
committed
MWPW-179684: Add GenAI guidelines support
Add genAI property to AI verbs and use verb-widget-legal-2-ai for AI-specific legal text
1 parent 8e8905c commit f767d52

File tree

2 files changed

+259
-1
lines changed

2 files changed

+259
-1
lines changed

acrobat/blocks/verb-widget/verb-widget.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export const LIMITS = {
8787
multipleFiles: true,
8888
uploadType: 'multifile-only',
8989
subCopy: true,
90+
genAI: true,
9091
},
9192
'chat-pdf': {
9293
maxFileSize: 104857600, // 100 MB
@@ -96,13 +97,15 @@ export const LIMITS = {
9697
multipleFiles: true,
9798
uploadType: 'multifile-only',
9899
subCopy: true,
100+
genAI: true,
99101
},
100102
'summarize-pdf': {
101103
maxFileSize: 104857600, // 100 MB
102104
maxFileSizeFriendly: '1 MB',
103105
acceptedFiles: ['.pdf', '.doc', '.docx', '.xml', '.ppt', '.pptx', '.xls', '.xlsx', '.rtf', '.txt', '.text', '.ai', '.form', '.bmp', '.gif', '.indd', '.jpeg', '.jpg', '.png', '.psd', '.tif', '.tiff'],
104106
maxNumFiles: 1,
105107
subCopy: true,
108+
genAI: true,
106109
},
107110
'split-pdf': {
108111
maxFileSize: 104857600, // 1 GB
@@ -629,6 +632,7 @@ export default async function init(element) {
629632
const { locale } = getConfig();
630633
const ppURL = window.mph['verb-widget-privacy-policy-url'] || `https://www.adobe.com${locale.prefix}/privacy/policy.html`;
631634
const touURL = window.mph['verb-widget-terms-of-use-url'] || `https://www.adobe.com${locale.prefix}/legal/terms.html`;
635+
const genAIurl = window.mph['verb-widget-genai-terms-url'] || `https://www.adobe.com${locale.prefix}/legal/licenses-terms/adobe-gen-ai-user-guidelines.html`;
632636

633637
const children = element.querySelectorAll(':scope > div');
634638
const VERB = element.classList[1];
@@ -785,7 +789,18 @@ export default async function init(element) {
785789
}
786790

787791
if (!(LIMITS[VERB].mobileApp && isMobile)) {
788-
legalTwo.innerHTML = legalTwo.textContent.replace(window.mph['verb-widget-terms-of-use'], `<a class="verb-legal-url" target="_blank" href="${touURL}">${window.mph['verb-widget-terms-of-use']}</a>`).replace(window.mph['verb-widget-privacy-policy'], `<a class="verb-legal-url" target="_blank" href="${ppURL}">${window.mph['verb-widget-privacy-policy']}</a>`);
792+
const createLegalLink = (text, url) => `<a class="verb-legal-url" target="_blank" href="${url}">${text}</a>`;
793+
794+
const legalLinks = [
795+
['verb-widget-terms-of-use', touURL],
796+
['verb-widget-privacy-policy', ppURL],
797+
...(LIMITS[VERB].genAI ? [['verb-widget-genai-guidelines', genAIurl]] : []),
798+
];
799+
800+
legalTwo.innerHTML = legalLinks.reduce((html, [key, url]) => {
801+
const text = window.mph[key];
802+
return text ? html.replace(text, createLegalLink(text, url)) : html;
803+
}, (LIMITS[VERB].genAI && window.mph['verb-widget-legal-2-ai']) || legalTwo.textContent);
789804

790805
legalWrapper.append(legal, legalTwo);
791806
footer.append(iconSecurity, legalWrapper, infoIcon);
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/* eslint-disable compat/compat */
2+
import { readFile } from '@web/test-runner-commands';
3+
import { expect } from '@esm-bundle/chai';
4+
import sinon from 'sinon';
5+
import { getConfig, setConfig } from 'https://main--milo--adobecom.hlx.live/libs/utils/utils.js'; // eslint-disable-line import/no-unresolved
6+
import { delay } from '../../helpers/waitfor.js';
7+
8+
const { default: init } = await import(
9+
'../../../acrobat/blocks/verb-widget/verb-widget.js'
10+
);
11+
12+
describe('verb-widget legal text with LIMITS-based AI support', () => {
13+
let xhr;
14+
let placeholders;
15+
16+
beforeEach(async () => {
17+
sinon.stub(window, 'fetch');
18+
window.fetch.callsFake((x) => {
19+
if (x.endsWith('.svg')) {
20+
return window.fetch.wrappedMethod.call(window, x);
21+
}
22+
return Promise.resolve();
23+
});
24+
25+
const placeholdersText = await readFile({ path: './mocks/placeholders.json' });
26+
placeholders = JSON.parse(placeholdersText);
27+
28+
window.mph = {};
29+
placeholders.data.forEach((item) => {
30+
window.mph[item.key] = item.value;
31+
});
32+
33+
// Add AI-specific legal text for genAI verbs
34+
window.mph['verb-widget-legal-2-ai'] = 'AI legal text with Terms of Use, Privacy Policy, and GenAI Guidelines';
35+
window.mph['verb-widget-genai-guidelines'] = 'GenAI Guidelines';
36+
37+
xhr = sinon.useFakeXMLHttpRequest();
38+
document.head.innerHTML = await readFile({ path: './mocks/head.html' });
39+
document.body.innerHTML = await readFile({ path: './mocks/body-sign-pdf.html' });
40+
window.adobeIMS = { isSignedInUser: () => false };
41+
});
42+
43+
afterEach(() => {
44+
xhr.restore();
45+
sinon.restore();
46+
});
47+
48+
it('non-AI verbs use default legal text only', async () => {
49+
const conf = getConfig();
50+
setConfig({ ...conf, locale: { prefix: '' } });
51+
const block = document.body.querySelector('.verb-widget');
52+
await init(block);
53+
await delay(100);
54+
55+
// fillsign is not an AI verb, so it uses default placeholders
56+
const legalElements = block.querySelectorAll('.verb-legal');
57+
expect(legalElements).to.have.lengthOf(2);
58+
59+
const legalText = legalElements[0].textContent.trim();
60+
const legalTwoText = legalElements[1].textContent.trim();
61+
62+
// Should use default legal text from placeholders.json
63+
expect(legalText).to.equal('Your file will be securely handled by Adobe servers and deleted unless you sign in to save it.');
64+
expect(legalTwoText).to.equal('By using this service, you agree to the Adobe Terms of Use and Privacy Policy.');
65+
66+
// Check default terms and privacy links
67+
const termsLink = legalElements[1].querySelector('a[href*="legal/terms"]');
68+
const privacyLink = legalElements[1].querySelector('a[href*="privacy/policy"]');
69+
const genAILink = legalElements[1].querySelector('a[href*="adobe-gen-ai-user-guidelines"]');
70+
71+
expect(termsLink).to.exist;
72+
expect(privacyLink).to.exist;
73+
// fillsign is not an AI verb, so no GenAI link should exist
74+
expect(genAILink).to.not.exist;
75+
expect(termsLink.textContent).to.equal('Terms of Use');
76+
expect(privacyLink.textContent).to.equal('Privacy Policy');
77+
78+
// Check default tooltip
79+
const infoIcon = block.querySelector('.info-icon');
80+
expect(infoIcon.getAttribute('aria-label')).to.equal('Files are secured using HTTPS w/TLS 1.2 and stored using AES-256 encryption');
81+
});
82+
83+
it('uses AI-specific legal text for genAI verbs (chat-pdf)', async () => {
84+
// Change to chat-pdf verb which has genAI: true in LIMITS
85+
document.body.innerHTML = `<main>
86+
<div>
87+
<div class="verb-widget chat-pdf">
88+
<div><div><h1>Chat with PDF</h1></div></div>
89+
<div><div>{{verb-widget-legal}}</div></div>
90+
</div>
91+
<div class="unity workflow-acrobat"></div>
92+
</div>
93+
</main>`;
94+
95+
const conf = getConfig();
96+
setConfig({ ...conf, locale: { prefix: '' } });
97+
const block = document.body.querySelector('.verb-widget');
98+
await init(block);
99+
await delay(100);
100+
101+
const legalElements = block.querySelectorAll('.verb-legal');
102+
expect(legalElements).to.have.lengthOf(2);
103+
104+
// Should use AI-specific legal text
105+
const legalTwoText = legalElements[1].textContent.trim();
106+
expect(legalTwoText).to.equal('AI legal text with Terms of Use, Privacy Policy, and GenAI Guidelines');
107+
108+
// Should have GenAI guidelines link for AI verbs
109+
const genAILink = legalElements[1].querySelector('a[href*="adobe-gen-ai-user-guidelines"]');
110+
expect(genAILink).to.exist;
111+
expect(genAILink.textContent).to.equal('GenAI Guidelines');
112+
expect(genAILink.getAttribute('target')).to.equal('_blank');
113+
expect(genAILink.getAttribute('class')).to.equal('verb-legal-url');
114+
});
115+
116+
it('uses custom GenAI URL when provided for AI verbs', async () => {
117+
// Change to chat-pdf verb which has genAI: true
118+
document.body.innerHTML = `<main>
119+
<div>
120+
<div class="verb-widget chat-pdf">
121+
<div><div><h1>Chat with PDF</h1></div></div>
122+
<div><div>{{verb-widget-legal}}</div></div>
123+
</div>
124+
<div class="unity workflow-acrobat"></div>
125+
</div>
126+
</main>`;
127+
128+
// Set custom GenAI URL
129+
window.mph['verb-widget-genai-terms-url'] = 'https://custom.adobe.com/genai-terms';
130+
131+
const conf = getConfig();
132+
setConfig({ ...conf, locale: { prefix: '' } });
133+
const block = document.body.querySelector('.verb-widget');
134+
await init(block);
135+
await delay(100);
136+
137+
const legalElements = block.querySelectorAll('.verb-legal');
138+
const genAILink = legalElements[1].querySelector('a[href="https://custom.adobe.com/genai-terms"]');
139+
140+
expect(genAILink).to.exist;
141+
expect(genAILink.textContent).to.equal('GenAI Guidelines');
142+
});
143+
144+
it('AI verbs fall back to default legal-2 when verb-widget-legal-2-ai not available', async () => {
145+
// Change to chat-pdf verb which has genAI: true
146+
document.body.innerHTML = `<main>
147+
<div>
148+
<div class="verb-widget chat-pdf">
149+
<div><div><h1>Chat with PDF</h1></div></div>
150+
<div><div>{{verb-widget-legal}}</div></div>
151+
</div>
152+
<div class="unity workflow-acrobat"></div>
153+
</div>
154+
</main>`;
155+
156+
// Remove AI-specific legal text
157+
delete window.mph['verb-widget-legal-2-ai'];
158+
159+
const conf = getConfig();
160+
setConfig({ ...conf, locale: { prefix: '' } });
161+
const block = document.body.querySelector('.verb-widget');
162+
await init(block);
163+
await delay(100);
164+
165+
const legalElements = block.querySelectorAll('.verb-legal');
166+
167+
// Should fall back to default legal-2 text
168+
const legalTwoText = legalElements[1].textContent.trim();
169+
expect(legalTwoText).to.equal('By using this service, you agree to the Adobe Terms of Use and Privacy Policy.');
170+
171+
// GenAI link won't exist because default text doesn't contain GenAI Guidelines placeholder
172+
const genAILink = legalElements[1].querySelector('a[href*="adobe-gen-ai-user-guidelines"]');
173+
expect(genAILink).to.not.exist;
174+
});
175+
176+
it('AI verbs without genai-guidelines placeholder do not create GenAI link', async () => {
177+
// Change to chat-pdf verb which has genAI: true
178+
document.body.innerHTML = `<main>
179+
<div>
180+
<div class="verb-widget chat-pdf">
181+
<div><div><h1>Chat with PDF</h1></div></div>
182+
<div><div>{{verb-widget-legal}}</div></div>
183+
</div>
184+
<div class="unity workflow-acrobat"></div>
185+
</div>
186+
</main>`;
187+
188+
// Remove GenAI guidelines placeholder
189+
delete window.mph['verb-widget-genai-guidelines'];
190+
191+
const conf = getConfig();
192+
setConfig({ ...conf, locale: { prefix: '' } });
193+
const block = document.body.querySelector('.verb-widget');
194+
await init(block);
195+
await delay(100);
196+
197+
const legalElements = block.querySelectorAll('.verb-legal');
198+
199+
// Should use AI legal text but no GenAI link
200+
const legalTwoText = legalElements[1].textContent.trim();
201+
expect(legalTwoText).to.equal('AI legal text with Terms of Use, Privacy Policy, and GenAI Guidelines');
202+
203+
// No GenAI link should be created without the placeholder
204+
const genAILink = legalElements[1].querySelector('a[href*="adobe-gen-ai-user-guidelines"]');
205+
expect(genAILink).to.not.exist;
206+
});
207+
208+
it('handles missing placeholders gracefully', async () => {
209+
// Change to chat-pdf verb which has genAI: true
210+
document.body.innerHTML = `<main>
211+
<div>
212+
<div class="verb-widget chat-pdf">
213+
<div><div><h1>Chat with PDF</h1></div></div>
214+
<div><div>{{verb-widget-legal}}</div></div>
215+
</div>
216+
<div class="unity workflow-acrobat"></div>
217+
</div>
218+
</main>`;
219+
220+
// Remove some placeholders to test forEach with undefined values
221+
delete window.mph['verb-widget-terms-of-use'];
222+
delete window.mph['verb-widget-legal-2-ai'];
223+
224+
const conf = getConfig();
225+
setConfig({ ...conf, locale: { prefix: '' } });
226+
const block = document.body.querySelector('.verb-widget');
227+
await init(block);
228+
await delay(100);
229+
230+
const legalElements = block.querySelectorAll('.verb-legal');
231+
232+
// Should fall back to default legal-2 when AI text not available
233+
const legalTwoText = legalElements[1].textContent.trim();
234+
expect(legalTwoText).to.equal('By using this service, you agree to the Adobe Terms of Use and Privacy Policy.');
235+
236+
// Privacy link should still work, terms link should not exist
237+
const termsLink = legalElements[1].querySelector('a[href*="legal/terms"]');
238+
const privacyLink = legalElements[1].querySelector('a[href*="privacy/policy"]');
239+
240+
expect(termsLink).to.not.exist; // No terms placeholder
241+
expect(privacyLink).to.exist; // Privacy placeholder exists
242+
});
243+
});

0 commit comments

Comments
 (0)