Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitelist of Variable Substitutions #3

Open
wants to merge 68 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
cdbabc6
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
c221629
Added some functional tests
hamousavi Feb 5, 2018
ffbee60
Fix import ordering in amp-access-scroll (#13265)
rsimha Feb 5, 2018
332ca05
<amp-facebook-*>Add data-locale attribute (#13204)
nainar Feb 5, 2018
fba9fec
Document batchPlugin and how vendor add their plugin (#13065)
zhouyx Feb 5, 2018
910d343
:book: add AMP emoji conventional changelogs (#13037)
erwinmombay Feb 5, 2018
e2dedbd
cron job from @erwinmombay to update size.txt and size.csv (#13263)
donttrustthisbot Feb 5, 2018
d69a859
Rename lightbox viewer to lightbox gallery and clean up examples (#13…
cathyxz Feb 5, 2018
5e91864
Fix bookend image aspect scaling. (#13212)
newmuis Feb 5, 2018
b784439
amp-story video playback improvements (#13245)
newmuis Feb 5, 2018
0aad6b4
Story-Auto-Ads Skeleton (#13239)
calebcordry Feb 5, 2018
68aefae
Indicate progress during gulp lint (#13274)
rsimha Feb 5, 2018
c20c36e
Support `--extensions=minimal_set` & bug fix (#13249)
zhouyx Feb 5, 2018
a8e4f9e
Adding amp-story-analytics (#13276)
rudygalfi Feb 5, 2018
515e812
Fail build on error, and print a useful message (#13255)
rsimha Feb 5, 2018
00032a7
return with user error (#13279)
zhouyx Feb 5, 2018
a0f855b
Run lint and presubmit on gulpfile.js (#13258)
rsimha Feb 5, 2018
d8df163
🐛🖍️ Preventing publishers CSS from overriding stories system layer an…
gmajoulet Feb 6, 2018
686abe4
Make sure polyfills.js is imported before anything else (#13277)
rsimha Feb 6, 2018
fe9925c
Fix for broken snapping on IOS for slides (#13290)
camelburrito Feb 6, 2018
79c4969
Increase button tap target size and ghost image on enter (#13278)
cathyxz Feb 6, 2018
64d4ab3
Clean up wording in Media Session API section (#13273)
Feb 6, 2018
88d14b9
Fix 'gulp test --a4a' and remove '--randomize' (#13292)
rsimha Feb 6, 2018
4c86a54
Update amp-iframe container in build callback (#13242)
jridgewell Feb 6, 2018
56a4a20
Implement amp-byside-placeholder extension (#12798)
bysidedevel3rdparty Feb 6, 2018
7c1ce87
Hand icon for all lightboxed images (#13298)
cathyxz Feb 6, 2018
99a0424
Delete build-system/tasks/package.json, whitelist heroku page (#13295)
rsimha Feb 6, 2018
2ee9b80
amp-fx-collection: documentation (#13268)
aghassemi Feb 6, 2018
0a55db7
Added flag indicated renderStart implemented (#13062)
Feb 6, 2018
7ca49a9
Lightbox: only apply ghost to images going through transitions (#13301)
cathyxz Feb 6, 2018
ad97398
Remove unused A2A functionality for ALP (#13297)
Feb 6, 2018
14e352a
Add basic documentation for amp-lightbox-gallery (#13272)
cathyxz Feb 6, 2018
9125cfb
Don't cancel watch if an edit causes a compilation error (#13312)
rsimha Feb 6, 2018
dcfc50b
Tweak the Git instructions (#13112)
taymonbeal Feb 6, 2018
181eb76
Eslint: Remove unnecessary semicolons (#13323)
rsimha Feb 7, 2018
cc82c49
Compile all css with `gulp dist` (#13285)
zhouyx Feb 7, 2018
355cde7
Add cloudflare to caches.json (#13247)
lannka Feb 7, 2018
36936a7
Update eslint to the latest version 🚀 (#13252)
greenkeeper[bot] Feb 7, 2018
10b9469
Replaced "AMP Ads" with "AMPHTML ads" (#12923)
gabebender Feb 7, 2018
a941bda
Linear transitions for media story pages progress bar. (#13296)
gmajoulet Feb 7, 2018
3d54a68
Fix gulp test --a4a (#13331)
rsimha Feb 7, 2018
b630522
Resets and disables touch zoom for amp stories. (#13316)
Enriqe Feb 7, 2018
0de8ae2
Update Pubmine amp-ad to new 'async' implementation (#12855)
dbspringer Feb 7, 2018
bd9cdcc
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
6828fc4
Added some functional tests
hamousavi Feb 5, 2018
7b211a1
Fix flaky Karma startup by refreshing the `wd` cache (#13328)
rsimha Feb 7, 2018
e2c3db6
Clean up unnecessary dependency of ads/_config in A4A test. (#13342)
lannka Feb 7, 2018
3e41cb2
Update browserify to the latest version 🚀 (#13333)
greenkeeper[bot] Feb 7, 2018
537a7d9
amp-bind: Warn during verify instead of error (#13236)
Feb 7, 2018
8e92030
Change [state] usage from warning to error (#13237)
Feb 7, 2018
681ba06
Validator Rollup (#13338)
Gregable Feb 7, 2018
9673d3f
Add support for <amp-facebook-page> (#13261)
nainar Feb 7, 2018
9ee3b10
Nameframe experiment (#12708)
glevitzky Feb 7, 2018
a0325bc
Revert "Update browserify to the latest version 🚀" (#13347)
rsimha Feb 7, 2018
9865f0a
some refactoring
hamousavi Feb 7, 2018
5d9b64e
merged conflicts
hamousavi Feb 7, 2018
2a691ba
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
f42b66d
Added some functional tests
hamousavi Feb 5, 2018
b0df971
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
22ae973
Merge branch 'variable' of github.com:hamousavi/amphtml into variable
hamousavi Feb 7, 2018
3fe6c9b
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
83295f2
Added some functional tests
hamousavi Feb 5, 2018
15fec70
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
c245f55
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
8081b3c
Added some functional tests
hamousavi Feb 5, 2018
a82bf51
the code for whitelist of variables in url substitution. The code doe…
hamousavi Feb 5, 2018
5e87808
rebased
hamousavi Feb 7, 2018
d30d718
sync
hamousavi Feb 7, 2018
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
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"no-export-side-effect": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-semi": 2,
"no-for-of-statement": 2,
"no-implicit-coercion": [2, { "boolean": false }],
"no-implied-eval": 2,
Expand Down
16 changes: 16 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,19 @@ Bullet points like
really help with making this more readable.

Fixes/Closes/Related-to #1 (enter issue number, except in rare cases where none exists).

It is also helpful to add an emoji before the commit message to identify the kind of work done on a single commit. See the following suggestions below:

- :bug: - `:bug:` Bug fix
- :sparkles: - `:sparkles:` New feature
- :white_check_mark: - `:white_check_mark:` Tests
- :fire: - `:fire:` P0
- :rocket: - `:rocket:` Performance improvements
- :crayon: - `:crayon:` CSS / Styling
- :wheelchair: - `:wheelchair:` Accessibility
- :globe_with_meridians: - `:globe_with_meridians:` i18n (Internationalization)
- :book: - `:book:` Documentation
- :recycle: - `:recycle:` Refactoring (like moving around code w/o any changes)
- :building_construction: - `:building_construction:` Infrastructure / Tooling / Builds / CI
- :rewind: - `:rewind:` Revert
- :put_litter_in_its_place: - `:put_litter_in_its_place:` Deleting code
5 changes: 4 additions & 1 deletion 3p/ampcontext-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import './polyfills';

// src/polyfills.js must be the first import.
import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6

import {AmpContext} from './ampcontext.js';
import {initLogConstructor, setReportError} from '../src/log';

Expand Down
8 changes: 4 additions & 4 deletions 3p/ampcontext.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export class AbstractAmpContext {
});

return unlisten;
};
}

/**
* Requests HTML snippet from the parent window.
Expand Down Expand Up @@ -216,7 +216,7 @@ export class AbstractAmpContext {
'width': width,
'height': height,
}));
};
}

/**
* Allows a creative to set the callback function for when the resize
Expand All @@ -228,7 +228,7 @@ export class AbstractAmpContext {
onResizeSuccess(callback) {
this.client_.registerCallback(MessageType.EMBED_SIZE_CHANGED, obj => {
callback(obj['requestedHeight'], obj['requestedWidth']); });
};
}

/**
* Allows a creative to set the callback function for when the resize
Expand All @@ -241,7 +241,7 @@ export class AbstractAmpContext {
this.client_.registerCallback(MessageType.EMBED_SIZE_DENIED, obj => {
callback(obj['requestedHeight'], obj['requestedWidth']);
});
};
}

/**
* Takes the current name on the window, and attaches it to
Expand Down
2 changes: 1 addition & 1 deletion 3p/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,4 @@ export function installEmbedStateListener() {
listenParent(window, 'embed-state', function(data) {
inViewport = data.inViewport;
});
};
}
32 changes: 28 additions & 4 deletions 3p/facebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {user} from '../src/log';
* @param {!Window} global
* @param {function(!Object)} cb
*/
function getFacebookSdk(global, cb) {
loadScript(global, 'https://connect.facebook.net/' + dashToUnderline(window.navigator.language) + '/sdk.js', () => {
function getFacebookSdk(global, cb, locale) {
loadScript(global, 'https://connect.facebook.net/' + locale + '/sdk.js', () => {
cb(global.FB);
});
}
Expand Down Expand Up @@ -58,6 +58,27 @@ function getPostContainer(global, data) {
return container;
}

/**
* Create DOM element for the Facebook embedded page plugin.
* Reference: https://developers.facebook.com/docs/plugins/page-plugin
* @param {!Window} global
* @param {!Object} data The element data
* @return {!Element} div
*/
function getPageContainer(global, data) {
const container = global.document.createElement('div');
container.className = 'fb-page';
container.setAttribute('data-href', data.href);
container.setAttribute('data-tabs', data.tabs);
container.setAttribute('data-hide-cover', data.hideCover);
container.setAttribute('data-show-facepile', data.showFacePile);
container.setAttribute('data-hide-cta', data.hideCta);
container.setAttribute('data-small-header', data.smallHeader);
container.setAttribute(
'data-adapt-container-width', data.adaptContainerWidth);
return container;
}

/**
* Create DOM element for the Facebook comments plugin:
* Reference: https://developers.facebook.com/docs/plugins/comments
Expand Down Expand Up @@ -104,7 +125,10 @@ function getLikeContainer(global, data) {
export function facebook(global, data) {
const extension = global.context.tagName;
let container;
if (extension === 'AMP-FACEBOOK-LIKE') {

if (extension === 'AMP-FACEBOOK-PAGE') {
container = getPageContainer(global, data);
} else if (extension === 'AMP-FACEBOOK-LIKE') {
container = getLikeContainer(global, data);
} else if (extension === 'AMP-FACEBOOK-COMMENTS') {
container = getCommentsContainer(global, data);
Expand All @@ -126,5 +150,5 @@ export function facebook(global, data) {
});

FB.init({xfbml: true, version: 'v2.5'});
});
}, data.locale ? data.locale : dashToUnderline(window.navigator.language));
}
2 changes: 1 addition & 1 deletion 3p/frame-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function getContextState() {
startTime: rawContext['startTime'],
tagName: rawContext['tagName'],
};
};
}


/**
Expand Down
5 changes: 4 additions & 1 deletion 3p/iframe-transport-client-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import './polyfills';

// src/polyfills.js must be the first import.
import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6

import {IframeTransportClient} from './iframe-transport-client.js';
import {initLogConstructor, setReportError} from '../src/log';

Expand Down
6 changes: 4 additions & 2 deletions 3p/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
* https://3p.ampproject.net/$version/f.js
*/

import './polyfills';
// src/polyfills.js must be the first import.
import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6

import {AmpEvents} from '../src/amp-events';
import {
IntegrationAmpContext,
Expand Down Expand Up @@ -460,7 +462,7 @@ export function draw3p(win, data, configCallback) {
} else {
run(type, win, data);
}
};
}

/**
* @return {boolean} Whether this is the master iframe.
Expand Down
44 changes: 33 additions & 11 deletions 3p/nameframe.max.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,48 @@
<head>
<meta charset="utf-8">
<script>
window.onload = function() {
var name_data;
var writeInBody = false;
var instantLoad = false;

var errorHandler = function(err) {
window.parent.postMessage({type: 'no-content', error: err.message}, '*');
window.name = '';
}

var render = function() {
try {
var name_data = JSON.parse(window.name);
if (!name_data || !name_data['creative']) {
throw new Error('Missing or incorrectly formatted JSON ' +
'input to nameframe');
}
document.open();
document.write(name_data['creative']);
document.close();
delete name_data['creative'];
window.name = JSON.stringify(name_data);
} catch (err) {
window.parent.postMessage(
{type: 'no-content', error: err.message}, '*');
window.name = '';
} catch (e) {
errorHandler(e);
}
};

try {
name_data = JSON.parse(window.name);
writeInBody = name_data['writeInBody'];
instantLoad = name_data['instantLoad'];
if (!name_data || !name_data['creative']) {
throw new Error('Missing or incorrectly formatted JSON ' +
'input to nameframe');
}
if (!writeInBody) {
instantLoad ? render() : (window.onload = render);
}
} catch (e) {
errorHandler(e);
}
</script>
</head>
<body style="visibility: hidden;">
<body>
<script>
if (writeInBody) {
instantLoad ? render() : (window.onload = render);
}
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion 3p/twitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ export function cleanupTweetId_(tweetid) {
}

return tweetid;
};
}
1 change: 1 addition & 0 deletions ads/_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export const adConfig = {
appnexus: {
prefetch: 'https://acdn.adnxs.com/ast/ast.js',
preconnect: 'https://ib.adnxs.com',
renderStartImplemented: true,
},

atomx: {
Expand Down
40 changes: 20 additions & 20 deletions ads/google/a4a/docs/a4a-readme.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
# AMP Ads
# AMPHTML ads

AMP Ads applies AMP’s core philosophy of reliable fast performance and great user experience to ads.
AMPHTML ads applies AMP’s core philosophy of reliable fast performance and great user experience to ads.

# AMP Ads
# AMPHTML ads

AMP Ads are written in AMP format - [A4A HTML](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (A variant of AMP HTML) + CSS. This means that ads can no longer have the ability to run arbitrary JavaScript - which is traditionally the number one cause of poor ad performance. Therefore, just like core AMP, the core ads JavaScript use-cases are built right into the AMP Open Source project which guarantees good behavior from ads.
AMPHTML ads are written in AMP format - [A4A HTML](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (A variant of AMP HTML) + CSS. This means that ads can no longer have the ability to run arbitrary JavaScript - which is traditionally the number one cause of poor ad performance. Therefore, just like core AMP, the core ads JavaScript use-cases are built right into the AMP Open Source project which guarantees good behavior from ads.

# Why are AMP Ads better than regular ads?
# Why are AMPHTML ads better than regular ads?

### Faster
AMP Ads are faster because on AMP pages they are requested early while rendering the page and immediately displayed just before the user is about to view the ad. Reduced file size of AMP Ads also increases speed.
AMPHTML ads are faster because on AMP pages they are requested early while rendering the page and immediately displayed just before the user is about to view the ad. Reduced file size of AMPHTML ads also increases speed.

### More Aware
On AMP pages, the AMP runtime can coordinate a mobile phone's limited resources to the right component at the right time to give the best user experience. For example, AMP Ads with animations are paused when not in the current viewport.
On AMP pages, the AMP runtime can coordinate a mobile phone's limited resources to the right component at the right time to give the best user experience. For example, AMPHTML ads with animations are paused when not in the current viewport.

### Lighter
AMP Ads bundle commonly used ad functionality which removes bloat. Once on the page, AMP Ads also consume less resources. For example, instead of 10 trackers requesting their own information in regular ads, AMP Ads collect all the information once and distribute it to any number of interested trackers.
AMPHTML ads bundle commonly used ad functionality which removes bloat. Once on the page, AMPHTML ads also consume less resources. For example, instead of 10 trackers requesting their own information in regular ads, AMPHTML ads collect all the information once and distribute it to any number of interested trackers.

### More Engaging
"Users can't tap on ads they can't see". Faster ads lead to higher viewability and therefore higher click through rates, which ultimately leads to higher advertiser conversions.

### Safer
It's impossible to spread malware through advertising with AMP Ads. Not only are visitors safer, but advertiser brand perception cannot be negative.`
It's impossible to spread malware through advertising with AMPHTML ads. Not only are visitors safer, but advertiser brand perception cannot be negative.`

### More Flexible
AMP Ads are designed to work on both AMP and Non-AMP webpages, including desktop where the ad tagging library supports it. (e.g. GPT)
AMPHTML ads are designed to work on both AMP and Non-AMP webpages, including desktop where the ad tagging library supports it. (e.g. GPT)

# Current status

The AMP Ads format spec has been [released](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) and any creative developer can create AMP Ads. A number of ad providers are working on automatically converting ads to AMP Ads whenever possible. e.g. AdSense.
The AMPHTML ads format spec has been [released](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) and any creative developer can create AMPHTML ads. A number of ad providers are working on automatically converting ads to AMPHTML ads whenever possible. e.g. AdSense.

Here is how you can participate. If you are:

## Publishers

If publishers want to serve their direct-sold ad formats they must create the ads in [A4A format](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (or use a creative agency), and deliver them using an AMP Ad supported ad server.

The following adservers support serving AMP Ads at the moment:
The following adservers support serving AMPHTML ads at the moment:
1. DoubleClick for Publishers
2. TripleLift
3. Dianomi
Expand All @@ -48,7 +48,7 @@ Fast Fetch supports Real Time Config: publisher-specified, multiple, simultaneou

## Creative Agencies

If you are a creative agency, please express interest via [this form](https://goo.gl/forms/P2zpQT3aIEU1UsWj2) so we can include you in any outreach that's AMP Ads-related.
If you are a creative agency, please express interest via [this form](https://goo.gl/forms/P2zpQT3aIEU1UsWj2) so we can include you in any outreach that's AMPHTML-related.

## Ad Networks/ Ad Servers

Expand All @@ -60,27 +60,27 @@ Ad networks and ad servers can integrate with [Cloudflare](https://blog.cloudfla
#### Are there any AMP Ad samples?
Yes. A number of great looking ads developed in AMP format can be found [here](https://ampbyexample.com/amp-ads/#amp-ads/experimental_ads). They use advanced components in AMP. They give the user a great experience while ensuring that the performance remains great.

#### Are there any tools to create AMP Ads?
Yes. [Celtra](http://www.prnewswire.com/news-releases/celtra-partners-with-the-amp-project-showcases-amp-ad-creation-at-google-io-event-300459514.html) provides out of the box support for AMP ads in their ad creator platform. Other tools like [Google Web Designer](https://www.google.com/webdesigner/) are also in the process of adding support.
#### Are there any tools to create ads in AMPHTML?
Yes. [Celtra](http://www.prnewswire.com/news-releases/celtra-partners-with-the-amp-project-showcases-amp-ad-creation-at-google-io-event-300459514.html) provides out of the box support for AMPHTML ads in their ad creator platform. Other tools like [Google Web Designer](https://www.google.com/webdesigner/) are also in the process of adding support.

#### How can I verify that an AMP Ad is valid?
Depending on your development environment, there are a few options:
- Use the [AMP validator NPM](https://www.npmjs.com/package/amphtml-validator) module to build your own
- Use the [AMP validator](https://validator.ampproject.org/) for one off testing
- Partner with [Cloudflare](https://blog.cloudflare.com/firebolt/) and use their public validator end point.
On AMP pages, AMP ads must be valid in order to get them to render quickly. If not, the ads will still render but slower.
On AMP pages, AMPHTML ads must be valid in order to get them to render quickly. If not, the ads will still render but slower.


#### Do AMP Ads support 3rd party verification and viewability detection?
#### Do AMPHTML ads support 3rd party verification and viewability detection?
Yes, there is native support for verification and viewability detection using amp-analytics. (e.g. Google’s ActiveView integrates this way). There are also other vendors like MOAT that are actively implementing support for it.

#### Does AMP Ads support timeline based animation?
#### Does AMPHTML ads support timeline based animation?
Yes. Learn more about it [here](https://github.com/ampproject/amphtml/blob/master/extensions/amp-animation/amp-animation.md).

#### Most ads have tappable targets and configurable ad exits. Does AMP Ads have a similar mechanism?
#### Most ads have tappable targets and configurable ad exits. Does AMPHTML ads have a similar mechanism?
Yes. Learn more about it [here](https://github.com/ampproject/amphtml/blob/master/extensions/amp-ad-exit/amp-ad-exit.md).

#### Where can I learn more about AMP Ads?
#### Where can I learn more about AMPHTML ads?
The public [website](https://ampproject.org/ads) is a good place to start.

#### I can’t find what I need, where can I ask questions?
Expand Down
2 changes: 1 addition & 1 deletion ads/google/a4a/test/test-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ describe('GoogleAdLifecycleReporter', () => {
/&st=30/.test(src));
slotCounts[slotId] = slotCounts[slotId] || 0;
++slotCounts[slotId];
};
}
// SlotId 0 corresponds to unusedReporter, so ignore it.
for (let s = 1; s <= nSlots; ++s) {
expect(slotCounts[s], 'slotCounts[' + s + ']').to.equal(nStages);
Expand Down
2 changes: 1 addition & 1 deletion ads/google/a4a/test/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
} from '../utils';
import {
MockA4AImpl,
} from '../../../../extensions/amp-a4a/0.1/test/utils';;
} from '../../../../extensions/amp-a4a/0.1/test/utils';
import {Services} from '../../../../src/services';
import {buildUrl} from '../url-builder';
import {createElementWithAttributes} from '../../../../src/dom';
Expand Down
Loading