Skip to content

Commit

Permalink
hide placeholder when tweet is succesfully loaded (ampproject#35788)
Browse files Browse the repository at this point in the history
  • Loading branch information
kvchari authored and Mahir committed Sep 9, 2021
1 parent 1b3cd60 commit 0192b92
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 6 deletions.
2 changes: 2 additions & 0 deletions extensions/amp-twitter/1.0/amp-twitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class AmpTwitter extends BaseElement {
/** @override */
init() {
return dict({
'onLoad': () => this.togglePlaceholder(false),
'onError': () => this.togglePlaceholder(true),
'requestResize': (height) => this.attemptChangeHeight(height),
});
}
Expand Down
9 changes: 8 additions & 1 deletion extensions/amp-twitter/1.0/component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Preact from '#preact';
import {MessageType, ProxyIframeEmbed} from '#preact/component/3p-frame';

import {deserializeMessage} from '#core/3p-frame-messaging';
import {forwardRef} from '#preact/compat';
import {useCallback, useMemo, useState} from '#preact';
Expand All @@ -20,6 +21,8 @@ function TwitterWithRef(
conversation,
limit,
momentid,
onError,
onLoad,
options: optionsProps,
requestResize,
style,
Expand All @@ -45,9 +48,13 @@ function TwitterWithRef(
} else {
setHeight(height);
}

onLoad?.();
} else if (data['type'] === MessageType.NO_CONTENT) {
onError?.();
}
},
[requestResize]
[requestResize, onLoad, onError]
);
const options = useMemo(
() => ({
Expand Down
32 changes: 32 additions & 0 deletions extensions/amp-twitter/1.0/storybook/Basic.amp.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,35 @@ export const MutatedTweetId = () => {
</>
);
};

export const SwapPlaceholder = () => {
return (
<>
<button on="tap:AMP.setState({tweetid: '495719809695621121'})">
Load tweet
</button>
<amp-state id="tweetid">
<script type="application/json">1356304203044499462</script>
</amp-state>
<amp-twitter
width="375"
height="472"
layout="responsive"
data-amp-bind-data-tweetid="tweetid"
>
<blockquote placeholder class="twitter-tweet" data-lang="en">
<p>Placeholder is shown until the tweet is loaded.</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
</p>
</blockquote>
</amp-twitter>
</>
);
};
42 changes: 42 additions & 0 deletions extensions/amp-twitter/1.0/test/test-amp-twitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,47 @@ describes.realWin(
expect(newName).not.to.contain(originalTweetId);
expect(newName).to.contain(newTweetId);
});

it('should test toggling placeholder off', async () => {
element = createElementWithAttributes(doc, 'amp-twitter', {
'data-tweetid': '585110598171631616',
});
doc.body.appendChild(element);
await waitForRender();

const impl = await element.getImpl(false);
const togglePlaceholderStub = env.sandbox.stub(impl, 'togglePlaceholder');

const iframe = element.shadowRoot.querySelector('iframe');
const {sentinel} = JSON.parse(iframe.getAttribute('name')).attributes;
const mockEvent = new CustomEvent('message');
mockEvent.data = serializeMessage('embed-size', sentinel, {
height: '1000',
});
mockEvent.source = iframe.contentWindow;
win.dispatchEvent(mockEvent);

expect(togglePlaceholderStub).to.be.calledOnce.calledWith(false);
});

it('should test toggling placeholder on', async () => {
element = createElementWithAttributes(doc, 'amp-twitter', {
'data-tweetid': '585110598171631616',
});
doc.body.appendChild(element);
await waitForRender();

const impl = await element.getImpl(false);
const togglePlaceholderStub = env.sandbox.stub(impl, 'togglePlaceholder');

const iframe = element.shadowRoot.querySelector('iframe');
const {sentinel} = JSON.parse(iframe.getAttribute('name')).attributes;
const mockEvent = new CustomEvent('message');
mockEvent.data = serializeMessage('no-content', sentinel);
mockEvent.source = iframe.contentWindow;
win.dispatchEvent(mockEvent);

expect(togglePlaceholderStub).to.be.calledOnce.calledWith(true);
});
}
);
50 changes: 50 additions & 0 deletions extensions/amp-twitter/1.0/test/test-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,54 @@ describes.sandboxed('Twitter preact component v1.0', {}, (env) => {
wrapper.setProps({playable: false});
expect(spy.set).to.be.calledOnce;
});

it('should call onLoad when loaded', () => {
const onLoadSpy = env.sandbox.spy();
const onErrorSpy = env.sandbox.spy();

const wrapper = mount(
<Twitter
tweetid="1356304203044499462"
height="500"
width="500"
onLoad={onLoadSpy}
onError={onErrorSpy}
></Twitter>
);

const iframe = wrapper.find('iframe').getDOMNode();
const {sentinel} = JSON.parse(iframe.getAttribute('name')).attributes;
const mockEvent = new CustomEvent('message');
mockEvent.data = serializeMessage('embed-size', sentinel, {height: '1000'});
mockEvent.source = iframe.contentWindow;
window.dispatchEvent(mockEvent);

expect(onLoadSpy).to.have.been.calledOnce;
expect(onErrorSpy).not.to.have.been.called;
});

it('should call onError when error', () => {
const onErrorSpy = env.sandbox.spy();
const onLoadSpy = env.sandbox.spy();

const wrapper = mount(
<Twitter
tweetid="00000000111111"
height="500"
width="500"
onError={onErrorSpy}
onLoad={onLoadSpy}
></Twitter>
);

const iframe = wrapper.find('iframe').getDOMNode();
const {sentinel} = JSON.parse(iframe.getAttribute('name')).attributes;
const mockEvent = new CustomEvent('message');
mockEvent.data = serializeMessage('no-content', sentinel);
mockEvent.source = iframe.contentWindow;
window.dispatchEvent(mockEvent);

expect(onErrorSpy).to.have.been.calledOnce;
expect(onLoadSpy).not.to.have.been.called;
});
});
8 changes: 3 additions & 5 deletions src/preact/component/3p-frame.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {getOptionalSandboxFlags, getRequiredSandboxFlags} from '#core/3p-frame';
import {MessageType} from '#core/3p-frame-messaging';
import {sequentialIdGenerator} from '#core/data-structures/id-generator';
import {dict} from '#core/types/object';
import {includes} from '#core/types/string';
Expand Down Expand Up @@ -26,11 +27,8 @@ import {parseUrlDeprecated} from '../../url';
/** @type {!Object<string,function():void>} 3p frames for that type. */
export const countGenerators = {};

/** @enum {string} */
export const MessageType = {
// TODO(wg-bento): Add more types as they become needed.
EMBED_SIZE: 'embed-size',
};
/** re-exports variable to preserve compat with components that already import this */
export {MessageType};

// Block synchronous XHR in ad. These are very rare, but super bad for UX
// as they block the UI thread for the arbitrary amount of time until the
Expand Down

0 comments on commit 0192b92

Please sign in to comment.