Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
be78c2b
[MWPW-192702] Fixing issues observed from evaluating the errors in an…
arugupta1992 Apr 23, 2026
14d6e4f
[MWPW-189488, MWPW-189974] : Bug fixes (#742)
arugupta1992 Apr 23, 2026
dc69e3a
MWPW-191927 Implementing Config-Based A/B Testing (#747)
sanjayms01 Apr 27, 2026
6ce58c3
Revert "MWPW-191927 Implementing Config-Based A/B Testing" (#755)
sanjayms01 Apr 27, 2026
dbb7a0a
MWPW-191927 Implementing Config-Based A/B Testing (#756)
sanjayms01 Apr 28, 2026
7a06169
Revert "[MWPW-189488, MWPW-189974] : Bug fixes " (#758)
arugupta1992 Apr 28, 2026
9e5f123
Revert "[MWPW-192702] Fixing issues observed from evaluating the erro…
arugupta1992 Apr 28, 2026
008bbc2
[MWPW-193670] Wave2.1 - Image to video changes (#751)
arugupta1992 Apr 28, 2026
9d0bb31
MWPW-191633: Enable milolibs/unitylibs query params on CC stage URLs …
nkthakur48 May 4, 2026
8910ad6
Bug fixes + Added aspect ratio icons (#762)
arugupta1992 May 5, 2026
1531b93
MWPW-192736: Add check for milolibs query param (#746)
zagi25 May 5, 2026
68788cd
[MWPW-192382] Onboard Mindmap Maker for Study Space (#763)
maagrawal16 May 6, 2026
1841b6d
browser responsiveness support + few css fixes (#769)
arugupta1992 May 7, 2026
739a5f5
[MWPW-193434] Doodlebug Wave 2.2 Audio - Adding support for Text to S…
vipu0303 May 7, 2026
6e23d79
MWPW-194184: Fix cancel on 2nd Generate redirecting to Firefly instea…
sanjayms01 May 9, 2026
57f359f
MWPW-194159 + Some analytics fixes (#770)
arugupta1992 May 11, 2026
0eddf8c
Doodlebug Wave 2.2 Audio bug fixes. (#772)
vipu0303 May 12, 2026
f7dc912
[DOTCOM-185216] Accessibility fixes for Doodlebug Video wave
May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions test/core/workflow/workflow-acrobat/action-binder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,14 @@ describe('ActionBinder', () => {
it('should return false for flashcard-maker with image/jpeg', () => {
expect(actionBinder.isSameFileType('flashcard-maker', 'image/jpeg')).to.be.false;
});

it('should return false for mindmap-maker with application/pdf', () => {
expect(actionBinder.isSameFileType('mindmap-maker', 'application/pdf')).to.be.false;
});

it('should return false for mindmap-maker with image/jpeg', () => {
expect(actionBinder.isSameFileType('mindmap-maker', 'image/jpeg')).to.be.false;
});
});

describe('validateFiles', () => {
Expand Down Expand Up @@ -1034,6 +1042,21 @@ describe('ActionBinder', () => {
expect(result).to.be.true;
});

it('should handle redirect for returning user for mindmap-maker', async () => {
actionBinder.workflowCfg.enabledFeatures = ['mindmap-maker'];
localStorage.setItem('unity.user', 'test-user');
localStorage.setItem('mindmap-maker_attempts', '2');

const cOpts = { payload: {} };
const filesData = { test: 'data' };
const result = await actionBinder.handleRedirect(cOpts, filesData);

expect(cOpts.payload.newUser).to.be.false;
expect(cOpts.payload.attempts).to.equal('2+');
expect(actionBinder.getRedirectUrl.calledWith(cOpts)).to.be.true;
expect(result).to.be.true;
});

it('should handle redirect with feedback for multi-file validation failure', async () => {
actionBinder.multiFileValidationFailure = true;
const cOpts = { payload: {} };
Expand Down Expand Up @@ -1303,6 +1326,29 @@ describe('ActionBinder', () => {
expect(actionBinder.handleMultiFileUpload.calledWith(validFile)).to.be.true;
expect(actionBinder.handleSingleFileUpload.called).to.be.false;
});

it('should handle verbs that require multi-file upload for mindmap-maker', async () => {
actionBinder.workflowCfg = {
name: 'workflow-acrobat',
enabledFeatures: ['mindmap-maker'],
targetCfg: { verbsWithoutMfuToSfuFallback: ['compress-pdf', 'mindmap-maker'] },
};
const files = [
{ name: 'test1.pdf', type: 'application/pdf', size: 1048576 },
{ name: 'test2.pdf', type: 'application/pdf', size: 2097152 },
];
const validFile = [files[0]];
actionBinder.validateFiles.resolves({ isValid: true, validFiles: validFile });

await actionBinder.handleFileUpload(files);

expect(actionBinder.sanitizeFileName.calledTwice).to.be.true;
expect(actionBinder.filterFilesWithPdflite.called).to.be.true;
expect(actionBinder.validateFiles.called).to.be.true;
expect(actionBinder.initUploadHandler.called).to.be.true;
expect(actionBinder.handleMultiFileUpload.calledWith(validFile)).to.be.true;
expect(actionBinder.handleSingleFileUpload.called).to.be.false;
});
});

describe('continueInApp', () => {
Expand Down Expand Up @@ -1556,6 +1602,35 @@ describe('ActionBinder', () => {
extractSpy.restore();
});

it('should handle input change event with single file for mindmap-maker', async () => {
const el = document.createElement('input');
el.type = 'file';
const addEventListenerSpy = sinon.spy(el, 'addEventListener');
const block = { querySelector: sinon.stub().returns(el) };
const actMap = { input: 'upload' };
const extractSpy = sinon.spy(actionBinder, 'extractFiles');
const spy = sinon.spy(actionBinder, 'acrobatActionMaps');

await actionBinder.initActionListeners(block, actMap);

const handler = addEventListenerSpy.getCalls().find((call) => call.args[0] === 'change').args[1];
actionBinder.signedOut = false;
actionBinder.tokenError = null;
actionBinder.workflowCfg.enabledFeatures = ['mindmap-maker'];

const file = new File(['test content'], 'test.pdf', { type: 'application/pdf' });
const event = { target: { files: [file], value: '' } };

await handler(event);

expect(extractSpy.called).to.be.true;
expect(spy.called).to.be.true;
expect(spy.firstCall.args).to.deep.equal(['upload', [file], file.size, 'change']);

spy.restore();
extractSpy.restore();
});

it('should handle input element not found', async () => {
const block = { querySelector: sinon.stub().returns(null) };
const actMap = { 'nonexistent-input': 'upload' };
Expand Down Expand Up @@ -1802,6 +1877,26 @@ describe('ActionBinder', () => {
{ code: 'pre_upload_error_missing_verb_config' },
)).to.be.true;
});

it('should not dispatch error when enabledFeatures[0] is mindmap-maker', async () => {
actionBinder.dispatchErrorToast.resetHistory();
actionBinder.processSingleFile = sinon.stub().resolves();
actionBinder.processHybrid = sinon.stub().resolves();
actionBinder.workflowCfg.enabledFeatures = ['mindmap-maker'];
const validFiles = [
{ name: 'test.pdf', type: 'application/pdf', size: 1048576 },
];
const totalFileSize = validFiles.reduce((sum, file) => sum + file.size, 0);
await actionBinder.acrobatActionMaps('upload', validFiles, totalFileSize, 'test-event');
expect(actionBinder.dispatchErrorToast.neverCalledWith(
'error_generic',
500,
'Invalid or missing verb configuration on Unity',
false,
true,
{ code: 'pre_upload_error_missing_verb_config' },
)).to.be.true;
});
});
});

Expand Down Expand Up @@ -2006,6 +2101,26 @@ describe('ActionBinder', () => {
localStorageStub.restore();
actionBinder.getRedirectUrl.restore();
});

it('should handle localStorage access error for mindmap-maker', async () => {
actionBinder.workflowCfg.enabledFeatures = ['mindmap-maker'];
const localStorageStub = sinon.stub(window.localStorage, 'getItem');
localStorageStub.throws(new Error('localStorage not available'));

const cOpts = { payload: {} };
const filesData = { type: 'application/pdf', size: 123, count: 1 };
sinon.stub(actionBinder, 'getRedirectUrl').resolves();
actionBinder.redirectUrl = 'https://test-redirect.com';

const result = await actionBinder.handleRedirect(cOpts, filesData);

expect(result).to.be.true;
expect(cOpts.payload.newUser).to.be.true;
expect(cOpts.payload.attempts).to.equal('1st');

localStorageStub.restore();
actionBinder.getRedirectUrl.restore();
});
});

describe('Experiment Data Integration', () => {
Expand Down
30 changes: 15 additions & 15 deletions test/core/workflow/workflow-upload/action-binder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ describe('Unity Upload Block', () => {
actionBinder.serviceHandler = { showErrorToast: () => {} };

const invalidFile = new File(['test content'], 'test.txt', { type: 'text/plain' });
await actionBinder.uploadImage([invalidFile]);
await actionBinder.uploadFile([invalidFile]);
});

it('should show error for file size exceeding limit', async () => {
Expand All @@ -484,7 +484,7 @@ describe('Unity Upload Block', () => {
actionBinder.serviceHandler = { showErrorToast: () => {} };

const largeFile = new File(['x'.repeat(2000)], 'large.jpg', { type: 'image/jpeg' });
await actionBinder.uploadImage([largeFile]);
await actionBinder.uploadFile([largeFile]);
});

it('should show error for wrong number of files', async () => {
Expand All @@ -496,13 +496,13 @@ describe('Unity Upload Block', () => {
new File(['test1'], 'test1.jpg', { type: 'image/jpeg' }),
new File(['test2'], 'test2.jpg', { type: 'image/jpeg' }),
];
await actionBinder.uploadImage(files);
await actionBinder.uploadFile(files);
});

it('should handle null files', async () => {
const actionBinder = new ActionBinder(unityEl, workflowCfg, unityEl, [unityEl]);

await actionBinder.uploadImage(null);
await actionBinder.uploadFile(null);
});
});

Expand Down Expand Up @@ -978,7 +978,7 @@ describe('Unity Upload Block', () => {
const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });

try {
await actionBinder.uploadImage([file]);
await actionBinder.uploadFile([file]);
expect.fail('Should have thrown an error due to missing URL');
} catch (error) {
expect(error.message).to.equal('Error connecting to App');
Expand Down Expand Up @@ -1169,13 +1169,13 @@ describe('Unity Upload Block', () => {
expect(files).to.have.length(0);
});

it('should handle uploadImage with null files', async () => {
it('should handle uploadFile with null files', async () => {
const actionBinder = new ActionBinder(unityEl, workflowCfg, unityEl, [unityEl]);

await actionBinder.uploadImage(null);
await actionBinder.uploadFile(null);
});

it('should handle uploadImage with wrong number of files', async () => {
it('should handle uploadFile with wrong number of files', async () => {
const actionBinder = new ActionBinder(unityEl, workflowCfg, unityEl, [unityEl]);

actionBinder.serviceHandler = { showErrorToast: () => {} };
Expand All @@ -1185,20 +1185,20 @@ describe('Unity Upload Block', () => {
new File(['test2'], 'test2.jpg', { type: 'image/jpeg' }),
];

await actionBinder.uploadImage(files);
await actionBinder.uploadFile(files);
});

it('should handle uploadImage with invalid file type', async () => {
it('should handle uploadFile with invalid file type', async () => {
const actionBinder = new ActionBinder(unityEl, workflowCfg, unityEl, [unityEl]);

actionBinder.serviceHandler = { showErrorToast: () => {} };

const files = [new File(['test'], 'test.txt', { type: 'text/plain' })];

await actionBinder.uploadImage(files);
await actionBinder.uploadFile(files);
});

it('should handle uploadImage with file size exceeding limit', async () => {
it('should handle uploadFile with file size exceeding limit', async () => {
const testWorkflowCfg = {
productName: 'test-product',
targetCfg: {
Expand All @@ -1217,10 +1217,10 @@ describe('Unity Upload Block', () => {

const files = [new File(['x'.repeat(2000)], 'test.jpg', { type: 'image/jpeg' })];

await actionBinder.uploadImage(files);
await actionBinder.uploadFile(files);
});

it('should handle uploadImage with PSW feature enabled', async () => {
it('should handle uploadFile with PSW feature enabled', async () => {
const testWorkflowCfg = {
...workflowCfg,
pswFeature: true,
Expand Down Expand Up @@ -1256,7 +1256,7 @@ describe('Unity Upload Block', () => {
actionBinder.continueInApp = async () => Promise.resolve();

const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });
await actionBinder.uploadImage([file]);
await actionBinder.uploadFile([file]);

window.fetch = originalFetch;
actionBinder.checkImageDimensions = originalCheckImageDimensions;
Expand Down
16 changes: 10 additions & 6 deletions test/core/workflow/workflow.firefly.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ describe('Firefly Workflow Tests', () => {
unityElement = document.querySelector('.unity');
workflowCfg = {
name: 'workflow-firefly',
targetCfg: { renderWidget: true, insert: 'before', target: 'a:last-of-type' },
targetCfg: {
renderWidget: true,
insert: 'before',
target: 'a:last-of-type',
limits: { 'max-char-limit': 750 },
'limits-prompt-bar-audio': { 'max-char-limit': 5000 },
},
};
spriteContainer = '<svg></svg>';
block = document.querySelector('.unity-enabled');
Expand Down Expand Up @@ -1188,7 +1194,7 @@ describe('Firefly Workflow Tests', () => {
let event;

beforeEach(() => {
testWidget = new UnityWidget(block, unityElement, workflowCfg, spriteContainer);
testWidget = new UnityWidget(block, unityElement, { ...workflowCfg, targetCfg: { ...workflowCfg.targetCfg } }, spriteContainer);
testWidget.widgetWrap = document.createElement('div');
testWidget.widget = document.createElement('div');
testWidget.updateDropdownForVerb = sinon.stub();
Expand Down Expand Up @@ -2279,9 +2285,7 @@ describe('Firefly Workflow Tests', () => {
});

it('should pass empty object to logAnalytics when splunkData is omitted', async () => {
await testActionBinder.sendFireflyAnalytics(new CustomEvent('firefly-analytics', {
detail: { adobeEventName: 'Enter Prompt|UnityWidget' },
}));
await testActionBinder.sendFireflyAnalytics(new CustomEvent('firefly-analytics', { detail: { adobeEventName: 'Enter Prompt|UnityWidget' } }));
expect(logStub.calledOnceWithExactly('Enter Prompt|UnityWidget', {})).to.be.true;
});
});
Expand Down Expand Up @@ -2758,7 +2762,7 @@ describe('Firefly Workflow Tests', () => {
{ label: 'Var A', url: 'https://u1' },
{ label: 'Var B', url: 'https://u2' },
{ label: 'Var C', url: 'https://u3' },
{ label: 'Var D', url: 'https://u4' }
{ label: 'Var D', url: 'https://u4' },
]);
expect(pm.image).to.exist;
expect(pm.image[0].variations).to.deep.equal([]);
Expand Down
2 changes: 1 addition & 1 deletion test/utils/experiment-provider.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-underscore-dangle */
import { expect } from '@esm-bundle/chai';
import { getExperimentData, getDecisionScopesForVerb } from '../../unitylibs/utils/experiment-provider.js';
import getExperimentData, { getDecisionScopesForVerb } from '../../unitylibs/utils/experiment-provider.js';

describe('getExperimentData', () => {
// Helper function to setup mock with result and error
Expand Down
1 change: 1 addition & 0 deletions unitylibs/blocks/unity/unity.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function getUnityLibs(prodLibs, project = 'unity') {
return prodLibs;
}
const branch = new URLSearchParams(window.location.search).get('unitylibs') || 'main';
if (!/^[a-zA-Z0-9_-]+$/.test(branch)) throw new Error('Invalid branch name.');
const helixVersion = hostname.includes('.hlx.') ? 'hlx' : 'aem';
return branch.indexOf('--') > -1
? `https://${branch}.${helixVersion}.live/unitylibs`
Expand Down
Loading
Loading