Skip to content

Commit

Permalink
[MWPW-157017] Send a Link Feature - Implementation (#2804)
Browse files Browse the repository at this point in the history
* share link milo

* copy-link

* custom link

* updated poc

* updated poc

* unit tests

* eslint

* unit test

* reverted UT

* review comment

Co-authored-by: Okan Sahin <[email protected]>

* unit tests

* unit tests

* fallback changes

* fallback changes

* mobile only support

* fallback changes

* UT fix

* restructured code

* Code review changes

* Update styles.css

* query param reserved

* review comments

* Removed ipod

---------

Co-authored-by: Drashti Modasara <[email protected]>
Co-authored-by: Okan Sahin <[email protected]>
  • Loading branch information
3 people authored Sep 4, 2024
1 parent 94f5513 commit a5a33c5
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
4 changes: 4 additions & 0 deletions libs/styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,10 @@ a.static:hover {
text-decoration: underline;
}

.copy-link {
font-weight: 700;
}

/* Tooltip */
.tooltip-wrapper {
visibility: hidden;
Expand Down
22 changes: 22 additions & 0 deletions libs/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,24 @@ export function decorateAutoBlock(a) {
});
}

const decorateCopyLink = (a, evt) => {
const userAgent = navigator.userAgent.toLowerCase();
const isMobile = /android|iphone|mobile/.test(userAgent) && !/ipad/.test(userAgent);
if (!isMobile || !navigator.share) {
a.remove();
return;
}
const link = a.href.replace(evt, '');
const isConButton = ['EM', 'STRONG'].includes(a.parentElement.nodeName)
|| a.classList.contains('con-button');
if (!isConButton) a.classList.add('static', 'copy-link');
a.href = '';
a.addEventListener('click', async (e) => {
e.preventDefault();
if (navigator.share) await navigator.share({ title: link, url: link });
});
};

export function decorateLinks(el) {
const config = getConfig();
decorateImageLinks(el);
Expand Down Expand Up @@ -656,6 +674,10 @@ export function decorateLinks(el) {
window.adobeIMS?.signIn();
});
}
const copyEvent = '#_evt-copy';
if (a.href.includes(copyEvent)) {
decorateCopyLink(a, copyEvent);
}
return rdx;
}, []);
}
Expand Down
7 changes: 6 additions & 1 deletion test/utils/mocks/body.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@
<!-- Auto Block -->
<p><a class="autoblock" href="https://twitter.com/Adobe#_dnb">Auto Block</a></p>
<!-- Custom actions -->
<p><a class="login-action" href="https://www.adobe.com/#_evt-login"></a></p>
<p>
<a class="login-action" href="https://www.adobe.com/#_evt-login"></a>
</p>
<p>
<a class="copy-action" href="https://www.adobe.com/#_evt-copy"></a>
</p>
</div>
<div class="quote borders contained hide-block">
<div>
Expand Down
32 changes: 32 additions & 0 deletions test/utils/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,44 @@ describe('Utils', () => {
});

describe('Custom Link Actions', () => {
const originalUserAgent = navigator.userAgent;
before(() => {
window.navigator.share = sinon.stub().resolves();
Object.defineProperty(navigator, 'userAgent', {
value: 'android',
writable: true,
});
});

after(() => {
Object.defineProperty(navigator, 'userAgent', {
value: originalUserAgent,
writable: true,
});
});

it('Implements a login action', async () => {
await waitForElement('.login-action');
const login = document.querySelector('.login-action');
utils.decorateLinks(login);
expect(login.href).to.equal('https://www.stage.adobe.com/');
});
it('Implements a copy link action', async () => {
await waitForElement('.copy-action');
const copy = document.querySelector('.copy-action');
utils.decorateLinks(copy);
expect(copy.classList.contains('copy-link')).to.be.true;
});
it('triggers the event listener on clicking the custom links', async () => {
const login = document.querySelector('.login-action');
const copy = document.querySelector('.copy-action');
const clickEvent = new Event('click', { bubbles: true, cancelable: true });
const preventDefaultSpy = sinon.spy(clickEvent, 'preventDefault');
login.dispatchEvent(clickEvent);
copy.dispatchEvent(clickEvent);
expect(preventDefaultSpy.calledTwice).to.be.true;
expect(window.navigator.share.calledOnce).to.be.true;
});
});

describe('Fragments', () => {
Expand Down

0 comments on commit a5a33c5

Please sign in to comment.