Skip to content

Commit

Permalink
✨ [Story bookend] Created amp-story-social-share (#33077)
Browse files Browse the repository at this point in the history
* Created social-share

* Remove empty social share extension

* Fixed validation

* Updated validation

* Updated validation rule to pass test

* Remove comment

* Updated tests

* Added tests
  • Loading branch information
mszylkowski committed Mar 16, 2021
1 parent e36bcd1 commit d94427b
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 18 deletions.
52 changes: 52 additions & 0 deletions examples/amp-story/share.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!doctype html>
<html amp lang="en">
<head>
<meta charset="utf-8">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-story"
src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
<title>My Story</title>
<meta name="viewport"
content="width=device-width,minimum-scale=1,initial-scale=1">
<link rel="canonical" href="bookend.html">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<style amp-custom>
body {
font-family: 'Roboto', sans-serif;
}
amp-story-page {
background-color: white;
}
</style>
</head>

<body>
<amp-story
title="Bookend amp-story example"
publisher="The AMP Team"
publisher-logo-src="https://example.com/logo/1x1.png"
poster-portrait-src="https://example.com/my-story/poster/3x4.jpg"
poster-square-src="https://example.com/my-story/poster/1x1.jpg"
poster-landscape-src="https://example.com/my-story/poster/4x3.jpg"
standalone>

<amp-story-page id="cover">
<amp-story-grid-layer template="vertical">
<h1>Check the share providers</h1>
<h2>Should show Facebook and Whatsapp</h2>
</amp-story-grid-layer>
</amp-story-page>

<amp-story-social-share layout="nodisplay">
<script type="application/json">
{
"shareProviders": [
"facebook",
"whatsapp"
]
}
</script>
</amp-story-social-share>
</amp-story>
</body>
</html>
46 changes: 39 additions & 7 deletions extensions/amp-story/1.0/amp-story-request-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import {registerServiceBuilder} from '../../../src/service';
import {user, userAssert} from '../../../src/log';

/** @private @const {string} */
export const BOOKEND_CONFIG_ATTRIBUTE_NAME = 'src';
export const CONFIG_SRC_ATTRIBUTE_NAME = 'src';

/** @private const {string} */
export const BOOKEND_CREDENTIALS_ATTRIBUTE_NAME = 'data-credentials';
export const CREDENTIALS_ATTRIBUTE_NAME = 'data-credentials';

/** @private @const {string} */
const TAG = 'amp-story-request-service';
Expand All @@ -48,6 +48,9 @@ export class AmpStoryRequestService {

/** @const @type {function():(!Promise<!JsonObject>|!Promise<null>)} */
this.loadBookendConfig = once(() => this.loadBookendConfigImpl_());

/** @const @type {function():(!Promise<!JsonObject>|!Promise<null>)} */
this.loadShareConfig = once(() => this.loadShareConfigImpl_());
}

/**
Expand All @@ -66,11 +69,9 @@ export class AmpStoryRequestService {
return Promise.resolve(null);
}

if (bookendEl.hasAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME)) {
const rawUrl = bookendEl.getAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME);
const credentials = bookendEl.getAttribute(
BOOKEND_CREDENTIALS_ATTRIBUTE_NAME
);
if (bookendEl.hasAttribute(CONFIG_SRC_ATTRIBUTE_NAME)) {
const rawUrl = bookendEl.getAttribute(CONFIG_SRC_ATTRIBUTE_NAME);
const credentials = bookendEl.getAttribute(CREDENTIALS_ATTRIBUTE_NAME);
return this.executeRequest(rawUrl, credentials ? {credentials} : {});
}

Expand Down Expand Up @@ -102,6 +103,37 @@ export class AmpStoryRequestService {
return response.json();
});
}

/**
* Retrieves the publisher share providers.
* Has to be called through `loadShareConfig`.
* @return {(!Promise<!JsonObject>|!Promise<null>)}
*/
loadShareConfigImpl_() {
const shareConfigEl = childElementByTag(
this.storyElement_,
'amp-story-social-share'
);
if (!shareConfigEl) {
return this.loadBookendConfig();
}

if (shareConfigEl.hasAttribute(CONFIG_SRC_ATTRIBUTE_NAME)) {
const rawUrl = shareConfigEl.getAttribute(CONFIG_SRC_ATTRIBUTE_NAME);
const credentials = shareConfigEl.getAttribute(
CREDENTIALS_ATTRIBUTE_NAME
);
return this.executeRequest(rawUrl, credentials ? {credentials} : {});
}

// Fallback. Check for an inline json config.
let config = null;
try {
config = getChildJsonConfig(shareConfigEl);
} catch (err) {}

return Promise.resolve(config);
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion extensions/amp-story/1.0/amp-story-share.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ export class ShareWidget {
loadProviders() {
this.loadRequiredExtensions();

this.requestService_.loadBookendConfig().then((config) => {
this.requestService_.loadShareConfig().then((config) => {
const providers =
config &&
(config[SHARE_PROVIDERS_KEY] || config[DEPRECATED_SHARE_PROVIDERS_KEY]);
Expand Down
61 changes: 53 additions & 8 deletions extensions/amp-story/1.0/test/test-amp-story-request-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import {
AmpStoryRequestService,
BOOKEND_CONFIG_ATTRIBUTE_NAME,
BOOKEND_CREDENTIALS_ATTRIBUTE_NAME,
CONFIG_SRC_ATTRIBUTE_NAME,
CREDENTIALS_ATTRIBUTE_NAME,
} from '../amp-story-request-service';

describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
describes.fakeWin('amp-story-request-service', {amp: true}, (env) => {
let requestService;
let storyElement;
let bookendElement;
Expand All @@ -46,7 +46,7 @@ describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
it('should use the URL provided in the attribute to load the config', async () => {
const bookendUrl = 'https://publisher.com/bookend';

bookendElement.setAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME, bookendUrl);
bookendElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, bookendUrl);
xhrMock
.expects('fetchJson')
.withExactArgs(bookendUrl, {})
Expand All @@ -66,7 +66,7 @@ describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
const bookendUrl = 'https://publisher.com/bookend';
const fetchedConfig = 'amazingConfig';

bookendElement.setAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME, bookendUrl);
bookendElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, bookendUrl);
xhrMock
.expects('fetchJson')
.resolves({
Expand All @@ -85,7 +85,7 @@ describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
it('should fetch the bookend config once if called multiple times', async () => {
const bookendUrl = 'https://publisher.com/bookend';

bookendElement.setAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME, bookendUrl);
bookendElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, bookendUrl);
xhrMock
.expects('fetchJson')
.resolves({
Expand All @@ -104,8 +104,8 @@ describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
it('should fetch the bookend config with credentials', async () => {
const bookendUrl = 'https://publisher.com/bookend';

bookendElement.setAttribute(BOOKEND_CONFIG_ATTRIBUTE_NAME, bookendUrl);
bookendElement.setAttribute(BOOKEND_CREDENTIALS_ATTRIBUTE_NAME, 'include');
bookendElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, bookendUrl);
bookendElement.setAttribute(CREDENTIALS_ATTRIBUTE_NAME, 'include');
xhrMock
.expects('fetchJson')
.withExactArgs(bookendUrl, {
Expand All @@ -122,4 +122,49 @@ describes.fakeWin('amp-story-store-service', {amp: true}, (env) => {
await requestService.loadBookendConfig();
xhrMock.verify();
});

it('should return the expected social share config', async () => {
const shareUrl = 'https://publisher.com/bookend';
const fetchedConfig = 'amazingConfig';

const shareElement = env.win.document.createElement(
'amp-story-social-share'
);
storyElement.appendChild(shareElement);

shareElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, shareUrl);
xhrMock
.expects('fetchJson')
.resolves({
ok: true,
json() {
return Promise.resolve(fetchedConfig);
},
})
.once();

const config = await requestService.loadShareConfig();
expect(config).to.equal(fetchedConfig);
xhrMock.verify();
});

it('should return the social share config from the bookend', async () => {
const shareUrl = 'https://publisher.com/bookend';
const fetchedConfig = 'amazingConfig';

bookendElement.setAttribute(CONFIG_SRC_ATTRIBUTE_NAME, shareUrl);
xhrMock
.expects('fetchJson')
.resolves({
ok: true,
json() {
return Promise.resolve(fetchedConfig);
},
})
.once();

const config = await requestService.loadShareConfig();
expect(config).to.equal(fetchedConfig);
xhrMock.verify();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ amp-story/1.0/test/validator-amp-story-amp-experiment-error.html:61:6 Tag 'amp-e
| <!-- Invalid: amp-experiment not allowed as a child of amp-story -->
| <amp-experiment>
>> ^~~~~~~~~
amp-story/1.0/test/validator-amp-story-amp-experiment-error.html:77:4 Tag 'amp-experiment' is disallowed as child of tag 'amp-story'. Child tag must be one of ['amp-analytics', 'amp-consent', 'amp-geo', 'amp-pixel', 'amp-sidebar', 'amp-story-auto-ads', 'amp-story-auto-analytics', 'amp-story-bookend', 'amp-story-page']. (see https://amp.dev/documentation/components/amp-story)
amp-story/1.0/test/validator-amp-story-amp-experiment-error.html:77:4 Tag 'amp-experiment' is disallowed as child of tag 'amp-story'. Child tag must be one of ['amp-analytics', 'amp-consent', 'amp-geo', 'amp-pixel', 'amp-sidebar', 'amp-story-auto-ads', 'amp-story-auto-analytics', 'amp-story-bookend', 'amp-story-page', 'amp-story-social-share']. (see https://amp.dev/documentation/components/amp-story)
| <script type="application/json">
| {
| "background-color-test": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ amp-story/1.0/test/validator-amp-story-cta-layer-error.html:60:6 The attribute '
>> ^~~~~~~~~
amp-story/1.0/test/validator-amp-story-cta-layer-error.html:64:4 The tag 'amp-story-cta-layer' may only appear as a descendant of tag 'amp-story-page'.
>> ^~~~~~~~~
amp-story/1.0/test/validator-amp-story-cta-layer-error.html:64:4 Tag 'amp-story-cta-layer' is disallowed as child of tag 'amp-story'. Child tag must be one of ['amp-analytics', 'amp-consent', 'amp-geo', 'amp-pixel', 'amp-sidebar', 'amp-story-auto-ads', 'amp-story-auto-analytics', 'amp-story-bookend', 'amp-story-page']. (see https://amp.dev/documentation/components/amp-story)
amp-story/1.0/test/validator-amp-story-cta-layer-error.html:64:4 Tag 'amp-story-cta-layer' is disallowed as child of tag 'amp-story'. Child tag must be one of ['amp-analytics', 'amp-consent', 'amp-geo', 'amp-pixel', 'amp-sidebar', 'amp-story-auto-ads', 'amp-story-auto-analytics', 'amp-story-bookend', 'amp-story-page', 'amp-story-social-share']. (see https://amp.dev/documentation/components/amp-story)
| <a href="http://www.google.com" class="button"> Illegal CTA layer outside of amp-story-page! </a>
| </amp-story-cta-layer>
| </amp-story>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!doctype html>
<html amp lang="en">
<head>
<meta charset="utf-8">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-story"
src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
<title>My Story</title>
<meta name="viewport"
content="width=device-width,minimum-scale=1,initial-scale=1">
<link rel="canonical" href="bookend.html">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<style amp-custom>
body {
font-family: 'Roboto', sans-serif;
}
amp-story-page {
background-color: white;
}
</style>
</head>
<body>
<amp-story standalone title="My Story"
publisher="The AMP Team"
publisher-logo-src="https://example.com/logo/1x1.png"
poster-portrait-src="https://example.com/my-story/poster/3x4.jpg">
<amp-story-page id="cover">
<amp-story-grid-layer template="vertical">
<h1>Validation test for social-share providers</h1>
</amp-story-grid-layer>
</amp-story-page>
<!-- Valid social share tag -->
<amp-story-social-share layout="nodisplay">
<script type="application/json">
{
"shareProviders": [
"facebook",
"whatsapp"
]
}
</script>
</amp-story-social-share>
</amp-story>
</body>
</html>
46 changes: 46 additions & 0 deletions extensions/amp-story/1.0/test/validator-amp-story-social-share.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
PASS
| <!doctype html>
| <html amp lang="en">
| <head>
| <meta charset="utf-8">
| <script async src="https://cdn.ampproject.org/v0.js"></script>
| <script async custom-element="amp-story"
| src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
| <title>My Story</title>
| <meta name="viewport"
| content="width=device-width,minimum-scale=1,initial-scale=1">
| <link rel="canonical" href="bookend.html">
| <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
| <style amp-custom>
| body {
| font-family: 'Roboto', sans-serif;
| }
| amp-story-page {
| background-color: white;
| }
| </style>
| </head>
| <body>
| <amp-story standalone title="My Story"
| publisher="The AMP Team"
| publisher-logo-src="https://example.com/logo/1x1.png"
| poster-portrait-src="https://example.com/my-story/poster/3x4.jpg">
| <amp-story-page id="cover">
| <amp-story-grid-layer template="vertical">
| <h1>Validation test for social-share providers</h1>
| </amp-story-grid-layer>
| </amp-story-page>
| <!-- Valid social share tag -->
| <amp-story-social-share layout="nodisplay">
| <script type="application/json">
| {
| "shareProviders": [
| "facebook",
| "whatsapp"
| ]
| }
| </script>
| </amp-story-social-share>
| </amp-story>
| </body>
| </html>

0 comments on commit d94427b

Please sign in to comment.