diff --git a/extensions/amp-sidebar/0.1/test/test-amp-sidebar.js b/extensions/amp-sidebar/0.1/test/test-amp-sidebar.js
index 0390f944b572..66dd863245fd 100644
--- a/extensions/amp-sidebar/0.1/test/test-amp-sidebar.js
+++ b/extensions/amp-sidebar/0.1/test/test-amp-sidebar.js
@@ -16,16 +16,12 @@
*/
import {KeyCodes} from '../../../../src/utils/key-codes';
-import {adopt} from '../../../../src/runtime';
-import {createIframePromise} from '../../../../testing/iframe';
import {Services} from '../../../../src/services';
import {assertScreenReaderElement} from '../../../../testing/test-helper';
import {toggleExperiment} from '../../../../src/experiments';
-import * as sinon from 'sinon';
import '../amp-sidebar';
import * as lolex from 'lolex';
-adopt(window);
describes.realWin('amp-sidebar 0.1 version', {
win: { /* window spec */
@@ -36,54 +32,61 @@ describes.realWin('amp-sidebar 0.1 version', {
runtimeOn: false,
extensions: ['amp-sidebar:0.1'],
},
-}, () => {
- let sandbox;
+}, env => {
+ let win, doc;
let platform;
let clock;
let timer;
+ beforeEach(() => {
+ win = env.win;
+ doc = win.document;
+ timer = Services.timerFor(win);
+ platform = Services.platformFor(win);
+ });
+
function getAmpSidebar(options) {
options = options || {};
- return createIframePromise().then(iframe => {
- const ampSidebar = iframe.doc.createElement('amp-sidebar');
- const list = iframe.doc.createElement('ul');
- for (let i = 0; i < 10; i++) {
- const li = iframe.doc.createElement('li');
- li.innerHTML = 'Menu item ' + i;
- list.appendChild(li);
- }
- ampSidebar.appendChild(list);
- const anchor = iframe.doc.createElement('a');
- anchor.href = '#section1';
- ampSidebar.appendChild(anchor);
+ const ampSidebar = doc.createElement('amp-sidebar');
+ const list = doc.createElement('ul');
+ for (let i = 0; i < 10; i++) {
+ const li = doc.createElement('li');
+ li.innerHTML = 'Menu item ' + i;
+ list.appendChild(li);
+ }
+ ampSidebar.appendChild(list);
+ const anchor = doc.createElement('a');
+ anchor.href = '#section1';
+ ampSidebar.appendChild(anchor);
+ if (options.toolbars) {
+ getToolbars(options, ampSidebar);
+ }
+ if (options.side) {
+ ampSidebar.setAttribute('side', options.side);
+ }
+ if (options.open) {
+ ampSidebar.setAttribute('open', '');
+ }
+ if (options.closeText) {
+ ampSidebar.setAttribute('data-close-button-aria-label',
+ options.closeText);
+ };
+ ampSidebar.setAttribute('id', 'sidebar1');
+ ampSidebar.setAttribute('layout', 'nodisplay');
+ doc.body.appendChild(ampSidebar);
+ return ampSidebar.build().then(() => {
+ return ampSidebar.layoutCallback();
+ }).then(() => {
if (options.toolbars) {
- getToolbars(options, ampSidebar, iframe);
- }
- if (options.side) {
- ampSidebar.setAttribute('side', options.side);
- }
- if (options.open) {
- ampSidebar.setAttribute('open', '');
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
}
- if (options.closeText) {
- ampSidebar.setAttribute('data-close-button-aria-label',
- options.closeText);
- };
- ampSidebar.setAttribute('id', 'sidebar1');
- ampSidebar.setAttribute('layout', 'nodisplay');
- return iframe.addElement(ampSidebar).then(() => {
- timer = Services.timerFor(iframe.win);
- if (options.toolbars) {
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- }
- return {iframe, ampSidebar};
- });
+ return ampSidebar;
});
}
- function getToolbars(options, ampSidebar, iframe) {
+ function getToolbars(options, ampSidebar) {
// Stub our sidebar operations, doing this here as it will
// Ease testing our media queries
const impl = ampSidebar.implementation_;
@@ -98,10 +101,10 @@ describes.realWin('amp-sidebar 0.1 version', {
});
// Create our individual toolbars
options.toolbars.forEach(toolbarObj => {
- const navToolbar = iframe.doc.createElement('nav');
+ const navToolbar = doc.createElement('nav');
//Create/Set toolbar-target
- const toolbarTarget = iframe.doc.createElement('div');
+ const toolbarTarget = doc.createElement('div');
if (toolbarObj.toolbarTarget) {
toolbarTarget.setAttribute('id',
toolbarObj.toolbarTarget);
@@ -111,7 +114,7 @@ describes.realWin('amp-sidebar 0.1 version', {
toolbarTarget.setAttribute('id', 'toolbar-target');
navToolbar.setAttribute('toolbar-target', 'toolbar-target');
}
- iframe.win.document.body.appendChild(toolbarTarget);
+ doc.body.appendChild(toolbarTarget);
// Set the toolbar media
if (toolbarObj.media) {
@@ -119,9 +122,9 @@ describes.realWin('amp-sidebar 0.1 version', {
} else {
navToolbar.setAttribute('toolbar', '(min-width: 768px)');
}
- const toolbarList = iframe.doc.createElement('ul');
+ const toolbarList = doc.createElement('ul');
for (let i = 0; i < 3; i++) {
- const li = iframe.doc.createElement('li');
+ const li = doc.createElement('li');
li.innerHTML = 'Toolbar item ' + i;
toolbarList.appendChild(li);
}
@@ -131,18 +134,8 @@ describes.realWin('amp-sidebar 0.1 version', {
}
describe('amp-sidebar', () => {
- beforeEach(() => {
- sandbox = sinon.sandbox.create();
- platform = Services.platformFor(window);
- });
-
- afterEach(() => {
- sandbox.restore();
- });
-
it('should apply overlay class', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
expect(sidebarElement.classList.contains('i-amphtml-overlay'));
});
});
@@ -150,8 +143,7 @@ describes.realWin('amp-sidebar 0.1 version', {
it('should replace text to screen reader \
button in data-close-button-aria-label', () => {
return getAmpSidebar({'closeText':
- 'data-close-button-aria-label'}).then(obj => {
- const sidebarElement = obj.ampSidebar;
+ 'data-close-button-aria-label'}).then(sidebarElement => {
const closeButton = sidebarElement.lastElementChild;
expect(closeButton.textContent)
.to.equal('data-close-button-aria-label');
@@ -159,23 +151,19 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should open from left is side is not specified', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
expect(sidebarElement.getAttribute('side')).to.equal('left');
});
});
it('should open from right is side right is specified', () => {
- return getAmpSidebar({'side': 'right'}).then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar({'side': 'right'}).then(sidebarElement => {
expect(sidebarElement.getAttribute('side')).to.equal('right');
});
});
it('should create mask element in DOM', () => {
- return getAmpSidebar().then(obj => {
- const iframe = obj.iframe;
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
impl.vsync_ = {
mutate(callback) {
@@ -183,15 +171,14 @@ describes.realWin('amp-sidebar 0.1 version', {
},
};
impl.open_();
- expect(iframe.doc.querySelectorAll('.i-amphtml-sidebar-mask').length)
+ expect(doc.querySelectorAll('.i-amphtml-sidebar-mask').length)
.to.equal(1);
});
});
it('should create an invisible close \
button for screen readers only', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
impl.close_ = sandbox.spy();
const closeButton = sidebarElement.lastElementChild;
@@ -206,8 +193,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should open sidebar on button click', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
const historyPushSpy = sandbox.spy();
@@ -243,7 +229,7 @@ describes.realWin('amp-sidebar 0.1 version', {
expect(impl.scheduleLayout).to.not.be.called;
clock.tick(600);
- expect(obj.iframe.doc.activeElement).to.equal(sidebarElement);
+ expect(doc.activeElement).to.equal(sidebarElement);
expect(sidebarElement.style.display).to.equal('');
expect(impl.scheduleLayout).to.be.calledOnce;
@@ -257,8 +243,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should close sidebar on button click', () => {
- return getAmpSidebar({'open': true}).then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar({'open': true}).then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
impl.schedulePause = sandbox.spy();
@@ -302,8 +287,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should toggle sidebar on button click', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
impl.scheduleLayout = sandbox.spy();
@@ -317,12 +301,12 @@ describes.realWin('amp-sidebar 0.1 version', {
expect(sidebarElement.hasAttribute('open')).to.be.false;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
expect(sidebarElement.getAttribute('role')).to.equal('menu');
- expect(obj.iframe.doc.activeElement).to.not.equal(sidebarElement);
+ expect(doc.activeElement).to.not.equal(sidebarElement);
impl.toggle_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
clock.tick(600);
- expect(obj.iframe.doc.activeElement).to.equal(sidebarElement);
+ expect(doc.activeElement).to.equal(sidebarElement);
expect(sidebarElement.style.display).to.equal('');
expect(impl.scheduleLayout).to.be.calledOnce;
impl.toggle_();
@@ -335,9 +319,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should close sidebar on escape', () => {
- return getAmpSidebar().then(obj => {
- const iframe = obj.iframe;
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
impl.schedulePause = sandbox.spy();
@@ -350,14 +332,14 @@ describes.realWin('amp-sidebar 0.1 version', {
impl.open_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
if (eventObj.initEvent) {
eventObj.initEvent('keydown', true, true);
}
eventObj.keyCode = KeyCodes.ESCAPE;
eventObj.which = KeyCodes.ESCAPE;
- const el = iframe.doc.documentElement;
+ const el = doc.documentElement;
el.dispatchEvent ?
el.dispatchEvent(eventObj) : el.fireEvent('onkeydown', eventObj);
expect(sidebarElement.hasAttribute('open')).to.be.false;
@@ -369,8 +351,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should reflect state of the sidebar', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
impl.schedulePause = sandbox.spy();
@@ -411,8 +392,7 @@ describes.realWin('amp-sidebar 0.1 version', {
it.skip('should fix scroll leaks on ios safari', () => {
sandbox.stub(platform, 'isIos').returns(true);
sandbox.stub(platform, 'isSafari').returns(true);
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
impl.vsync_ = {
mutate(callback) {
@@ -431,8 +411,7 @@ describes.realWin('amp-sidebar 0.1 version', {
it.skip('should adjust for IOS safari bottom bar', () => {
sandbox.stub(platform, 'isIos').returns(true);
sandbox.stub(platform, 'isSafari').returns(true);
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
impl.vsync_ = {
mutate(callback) {
@@ -454,8 +433,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should close sidebar if clicked on a non-local anchor', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const anchor = sidebarElement.getElementsByTagName('a')[0];
anchor.href = '#newloc';
const impl = sidebarElement.implementation_;
@@ -470,8 +448,8 @@ describes.realWin('amp-sidebar 0.1 version', {
impl.open_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
if (eventObj.initEvent) {
eventObj.initEvent('click', true, true);
}
@@ -497,8 +475,7 @@ describes.realWin('amp-sidebar 0.1 version', {
it('should not close sidebar if \
clicked on a new origin navigation', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const anchor = sidebarElement.getElementsByTagName('a')[0];
anchor.href = '#newloc';
const impl = sidebarElement.implementation_;
@@ -515,8 +492,8 @@ describes.realWin('amp-sidebar 0.1 version', {
impl.open_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
if (eventObj.initEvent) {
eventObj.initEvent('click', true, true);
}
@@ -541,8 +518,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should not close sidebar if clicked on new page navigation', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const anchor = sidebarElement.getElementsByTagName('a')[0];
anchor.href = '#newloc';
const impl = sidebarElement.implementation_;
@@ -559,8 +535,8 @@ describes.realWin('amp-sidebar 0.1 version', {
impl.open_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
if (eventObj.initEvent) {
eventObj.initEvent('click', true, true);
}
@@ -586,8 +562,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should not close sidebar if clicked on non-anchor', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const li = sidebarElement.getElementsByTagName('li')[0];
const impl = sidebarElement.implementation_;
impl.schedulePause = sandbox.spy();
@@ -603,8 +578,8 @@ describes.realWin('amp-sidebar 0.1 version', {
impl.open_();
expect(sidebarElement.hasAttribute('open')).to.be.true;
expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
if (eventObj.initEvent) {
eventObj.initEvent('click', true, true);
}
@@ -619,8 +594,7 @@ describes.realWin('amp-sidebar 0.1 version', {
});
it('should listen to animationend/transitionend event', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
+ return getAmpSidebar().then(sidebarElement => {
const impl = sidebarElement.implementation_;
clock = lolex.install(impl.win, 0, ['Date', 'setTimeout']);
impl.boundOnAnimationEnd_ = sandbox.spy();
@@ -649,23 +623,14 @@ describes.realWin('amp-sidebar 0.1 version', {
describe('amp-sidebar - toolbars in amp-sidebar', () => {
beforeEach(() => {
- sandbox = sinon.sandbox.create();
- platform = Services.platformFor(window);
- toggleExperiment(window, 'amp-sidebar toolbar', true);
- });
-
- afterEach(() => {
- sandbox.restore();
+ toggleExperiment(win, 'amp-sidebar toolbar', true);
});
// Tests for amp-sidebar 1.0
it('should not create toolbars without ', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const headerElements = sidebarElement.ownerDocument
- .getElementsByTagName('header');
- const toolbarElements = sidebarElement.ownerDocument
- .querySelectorAll('[toolbar]');
+ return getAmpSidebar().then(sidebarElement => {
+ const headerElements = doc.getElementsByTagName('header');
+ const toolbarElements = doc.querySelectorAll('[toolbar]');
expect(headerElements.length).to.be.equal(0);
expect(toolbarElements.length).to.be.equal(0);
expect(sidebarElement.implementation_.toolbars_.length).to.be.equal(0);
@@ -675,8 +640,7 @@ describes.realWin('amp-sidebar 0.1 version', {
it('should create a toolbar element within the toolbar-target', () => {
return getAmpSidebar({
toolbars: [{}],
- }).then(obj => {
- const sidebarElement = obj.ampSidebar;
+ }).then(sidebarElement => {
expect(sidebarElement.implementation_.toolbars_.length)
.to.be.equal(1);
});
@@ -690,8 +654,7 @@ describes.realWin('amp-sidebar 0.1 version', {
media: '(min-width: 1024px)',
},
],
- }).then(obj => {
- const sidebarElement = obj.ampSidebar;
+ }).then(sidebarElement => {
expect(sidebarElement.implementation_.toolbars_.length)
.to.be.equal(2);
});
diff --git a/extensions/amp-sidebar/1.0/test/test-amp-sidebar.js b/extensions/amp-sidebar/1.0/test/test-amp-sidebar.js
index 65375436882b..2f9b97ce05ac 100644
--- a/extensions/amp-sidebar/1.0/test/test-amp-sidebar.js
+++ b/extensions/amp-sidebar/1.0/test/test-amp-sidebar.js
@@ -15,637 +15,612 @@
* limitations under the License.
*/
- import {KeyCodes} from '../../../../src/utils/key-codes';
- import {adopt} from '../../../../src/runtime';
- import {createIframePromise} from '../../../../testing/iframe';
- import {Services} from '../../../../src/services';
- import {assertScreenReaderElement} from '../../../../testing/test-helper';
- import {toggleExperiment} from '../../../../src/experiments';
- import * as sinon from 'sinon';
- import '../amp-sidebar';
-
- adopt(window);
-
- describes.realWin('amp-sidebar 1.0 version', {
- win: { /* window spec */
- location: '...',
- historyOff: false,
- },
- amp: { /* amp spec */
- runtimeOn: false,
- extensions: ['amp-sidebar:1.0'],
- },
- }, () => {
- describe('amp-sidebar', () => {
- let sandbox;
- let platform;
- let timer;
-
- function getAmpSidebar(options) {
- options = options || {};
- return createIframePromise().then(iframe => {
- const ampSidebar = iframe.doc.createElement('amp-sidebar');
- const list = iframe.doc.createElement('ul');
- for (let i = 0; i < 10; i++) {
- const li = iframe.doc.createElement('li');
- li.innerHTML = 'Menu item ' + i;
- list.appendChild(li);
- }
- ampSidebar.appendChild(list);
- const anchor = iframe.doc.createElement('a');
- anchor.href = '#section1';
- ampSidebar.appendChild(anchor);
- if (options.toolbars) {
- // Stub our sidebar operations, doing this here as it will
- // Ease testing our media queries
- const impl = ampSidebar.implementation_;
- sandbox.stub(impl.vsync_,
- 'mutate', callback => {
- callback();
- });
- sandbox.stub(impl.vsync_,
- 'mutatePromise', callback => {
- callback();
- return Promise.resolve();
- });
- // Create our individual toolbars
- options.toolbars.forEach(toolbarObj => {
- const navToolbar = iframe.doc.createElement('nav');
-
- //Create/Set toolbar-target
- const toolbarTarget = iframe.doc.createElement('div');
- if (toolbarObj.toolbarTarget) {
- toolbarTarget.setAttribute('id',
- toolbarObj.toolbarTarget);
- navToolbar.setAttribute('toolbar-target',
- toolbarObj.toolbarTarget);
- } else {
- toolbarTarget.setAttribute('id', 'toolbar-target');
- navToolbar.setAttribute('toolbar-target', 'toolbar-target');
- }
- iframe.win.document.body.appendChild(toolbarTarget);
-
- // Set the toolbar media
- if (toolbarObj.media) {
- navToolbar.setAttribute('toolbar', toolbarObj.media);
- } else {
- navToolbar.setAttribute('toolbar', '(min-width: 768px)');
- }
- const toolbarList = iframe.doc.createElement('ul');
- for (let i = 0; i < 3; i++) {
- const li = iframe.doc.createElement('li');
- li.innerHTML = 'Toolbar item ' + i;
- toolbarList.appendChild(li);
- }
- navToolbar.appendChild(toolbarList);
- ampSidebar.appendChild(navToolbar);
- });
- }
- if (options.side) {
- ampSidebar.setAttribute('side', options.side);
- }
- if (options.open) {
- ampSidebar.setAttribute('open', '');
- }
- if (options.closeText) {
- ampSidebar.setAttribute('data-close-button-aria-label',
- options.closeText);
- };
- ampSidebar.setAttribute('id', 'sidebar1');
- ampSidebar.setAttribute('layout', 'nodisplay');
- return iframe.addElement(ampSidebar).then(() => {
- timer = Services.timerFor(iframe.win);
- if (options.toolbars) {
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- }
- return {iframe, ampSidebar};
- });
- });
-
- it('should replace text to screen reader \
- button in data-close-button-aria-label', () => {
- return getAmpSidebar({'closeText':
- 'data-close-button-aria-label'}).then(obj => {
- const sidebarElement = obj.ampSidebar;
- const closeButton = sidebarElement.lastElementChild;
- expect(closeButton.textContent)
- .to.equal('data-close-button-aria-label');
- });
- });
- }
-
- beforeEach(() => {
- sandbox = sinon.sandbox.create();
- platform = Services.platformFor(window);
- toggleExperiment(window, 'amp-sidebar 1.0', true);
- });
-
- afterEach(() => {
- sandbox.restore();
- });
-
- it('should open from left is side is not specified', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- expect(sidebarElement.getAttribute('side')).to.equal('left');
- });
- });
-
- it('should open from right is side right is specified', () => {
- return getAmpSidebar({'side': 'right'}).then(obj => {
- const sidebarElement = obj.ampSidebar;
- expect(sidebarElement.getAttribute('side')).to.equal('right');
- });
- });
-
- it('should create mask element in DOM', () => {
- return getAmpSidebar().then(obj => {
- const iframe = obj.iframe;
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- impl.open_();
- expect(iframe.doc.querySelectorAll('.i-amphtml-sidebar-mask').length)
- .to.equal(1);
- });
- });
-
- it('should create an invisible close \
- button for screen readers only', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.close_ = sandbox.spy();
- const closeButton = sidebarElement.lastElementChild;
- expect(closeButton).to.exist;
- expect(closeButton.tagName).to.equal('BUTTON');
- assertScreenReaderElement(closeButton);
- expect(closeButton.textContent).to.equal('Close the sidebar');
- expect(impl.close_).to.have.not.been.called;
- closeButton.click();
- expect(impl.close_).to.be.calledOnce;
- });
- });
-
- it('should open sidebar on button click', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- const historyPushSpy = sandbox.spy();
- const historyPopSpy = sandbox.spy();
- impl.scheduleLayout = sandbox.spy();
- impl.getHistory_ = function() {
- return {
- push() {
- historyPushSpy();
- return Promise.resolve(11);
- },
- pop() {
- historyPopSpy();
- return Promise.resolve(11);
- },
- };
- };
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- timer.cancel = sandbox.spy();
- impl.openOrCloseTimeOut_ = 10;
-
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- expect(sidebarElement.getAttribute('role')).to.equal('menu');
- expect(obj.iframe.doc.activeElement).to.equal(sidebarElement);
- expect(sidebarElement.style.display).to.equal('');
- expect(timer.cancel).to.be.calledOnce;
- expect(impl.scheduleLayout).to.be.calledOnce;
- expect(historyPushSpy).to.be.calledOnce;
- expect(historyPopSpy).to.have.not.been.called;
- expect(impl.historyId_).to.not.equal('-1');
-
- // second call to open_() should be a no-op and not increase call counts.
- impl.open_();
- expect(impl.scheduleLayout).to.be.calledOnce;
- expect(historyPushSpy).to.be.calledOnce;
- expect(historyPopSpy).to.have.not.been.called;
-
- });
- });
-
- it('should close sidebar on button click', () => {
- return getAmpSidebar({'open': true}).then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- const historyPushSpy = sandbox.spy();
- const historyPopSpy = sandbox.spy();
- impl.scheduleLayout = sandbox.spy();
- impl.getHistory_ = function() {
- return {
- push() {
- historyPushSpy();
- return Promise.resolve(11);
- },
- pop() {
- historyPopSpy();
- return Promise.resolve(11);
- },
- };
- };
- impl.historyId_ = 100;
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
-
- timer.cancel = sandbox.spy();
- impl.openOrCloseTimeOut_ = 10;
- impl.close_();
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
- expect(sidebarElement.style.display).to.equal('none');
- expect(timer.cancel).to.be.calledOnce;
- expect(impl.schedulePause).to.be.calledOnce;
- expect(historyPopSpy).to.be.calledOnce;
- expect(impl.historyId_).to.equal(-1);
-
- // second call to close_() should be a no-op and not increase call counts.
- impl.close_();
- expect(impl.schedulePause).to.be.calledOnce;
- expect(historyPopSpy).to.be.calledOnce;
- });
- });
-
- it('should toggle sidebar on button click', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.scheduleLayout = sandbox.spy();
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
- expect(sidebarElement.getAttribute('role')).to.equal('menu');
- expect(obj.iframe.doc.activeElement).to.not.equal(sidebarElement);
- impl.toggle_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- expect(obj.iframe.doc.activeElement).to.equal(sidebarElement);
- expect(sidebarElement.style.display).to.equal('');
- expect(impl.scheduleLayout).to.be.calledOnce;
- impl.toggle_();
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
- expect(sidebarElement.style.display).to.equal('none');
- expect(impl.schedulePause).to.be.calledOnce;
- });
- });
-
- it('should close sidebar on escape', () => {
- return getAmpSidebar().then(obj => {
- const iframe = obj.iframe;
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
- if (eventObj.initEvent) {
- eventObj.initEvent('keydown', true, true);
- }
- eventObj.keyCode = KeyCodes.ESCAPE;
- eventObj.which = KeyCodes.ESCAPE;
- const el = iframe.doc.documentElement;
- el.dispatchEvent ?
- el.dispatchEvent(eventObj) : el.fireEvent('onkeydown', eventObj);
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
- expect(sidebarElement.style.display).to.equal('none');
- expect(impl.schedulePause).to.be.calledOnce;
- });
- });
-
- it('should reflect state of the sidebar', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.scheduleResume = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(impl.isOpen_()).to.be.false;
- expect(impl.schedulePause).to.have.not.been.called;
- expect(impl.scheduleResume).to.have.not.been.called;
- impl.toggle_();
- expect(impl.isOpen_()).to.be.true;
- expect(impl.schedulePause).to.have.not.been.called;
- expect(impl.scheduleResume).to.be.calledOnce;
- impl.toggle_();
- expect(impl.isOpen_()).to.be.false;
- expect(impl.schedulePause).to.be.calledOnce;
- expect(impl.scheduleResume).to.be.calledOnce;
- impl.toggle_();
- expect(impl.isOpen_()).to.be.true;
- expect(impl.schedulePause).to.be.calledOnce;
- expect(impl.scheduleResume).to.have.callCount(2);
- impl.toggle_();
- expect(impl.isOpen_()).to.be.false;
- expect(impl.schedulePause).to.have.callCount(2);
- expect(impl.scheduleResume).to.have.callCount(2);
- });
- });
-
- it.skip('should fix scroll leaks on ios safari', () => {
- sandbox.stub(platform, 'isIos').returns(true);
- sandbox.stub(platform, 'isSafari').returns(true);
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- const scrollLeakSpy = sandbox.spy(impl, 'fixIosElasticScrollLeak_');
- impl.buildCallback();
- expect(scrollLeakSpy).to.be.calledOnce;
- });
- });
-
- it.skip('should adjust for IOS safari bottom bar', () => {
- sandbox.stub(platform, 'isIos').returns(true);
- sandbox.stub(platform, 'isSafari').returns(true);
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const impl = sidebarElement.implementation_;
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- const compensateIosBottombarSpy =
- sandbox.spy(impl, 'compensateIosBottombar_');
- const initalChildrenCount = sidebarElement.children.length;
- impl.open_();
- expect(compensateIosBottombarSpy).to.be.calledOnce;
- // 10 lis + one top padding element inserted
- expect(sidebarElement.children.length)
- .to.equal(initalChildrenCount + 1);
- });
- });
-
- it('should close sidebar if clicked on a non-local anchor', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const anchor = sidebarElement.getElementsByTagName('a')[0];
- anchor.href = '#newloc';
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
- if (eventObj.initEvent) {
- eventObj.initEvent('click', true, true);
- }
- sandbox.stub(sidebarElement, 'getAmpDoc', () => {
- return {
- win: {
- location: {
- href: window.location.href,
- },
- },
- };
- });
- anchor.dispatchEvent ?
- anchor.dispatchEvent(eventObj) :
- anchor.fireEvent('onkeydown', eventObj);
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
- expect(sidebarElement.style.display).to.equal('none');
- expect(impl.schedulePause).to.be.calledOnce;
- });
- });
-
- it('should not close sidebar if \
- clicked on a new origin navigation', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const anchor = sidebarElement.getElementsByTagName('a')[0];
- anchor.href = '#newloc';
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
- if (eventObj.initEvent) {
- eventObj.initEvent('click', true, true);
- }
- sandbox.stub(sidebarElement, 'getAmpDoc', () => {
- return {
- win: {
- location: {
- // Mocking navigating from example.com -> localhost:9876
- href: 'http://example.com',
- },
- },
- };
- });
- anchor.dispatchEvent ?
- anchor.dispatchEvent(eventObj) :
- anchor.fireEvent('onkeydown', eventObj);
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- expect(sidebarElement.style.display).to.equal('');
- expect(impl.schedulePause).to.have.not.been.called;
- });
- });
-
- it('should not close sidebar if clicked on new page navigation', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const anchor = sidebarElement.getElementsByTagName('a')[0];
- anchor.href = '#newloc';
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
- if (eventObj.initEvent) {
- eventObj.initEvent('click', true, true);
- }
- sandbox.stub(sidebarElement, 'getAmpDoc', () => {
- return {
- win: {
- location: {
- // Mocking navigating from
- // /context.html?old=context -> /context.html
- href: 'http://localhost:9876/context.html?old=context',
- },
- },
- };
- });
- anchor.dispatchEvent ?
- anchor.dispatchEvent(eventObj) :
- anchor.fireEvent('onkeydown', eventObj);
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- expect(sidebarElement.style.display).to.equal('');
- expect(impl.schedulePause).to.have.not.been.called;
- });
- });
-
- it('should not close sidebar if clicked on non-anchor', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const li = sidebarElement.getElementsByTagName('li')[0];
- const impl = sidebarElement.implementation_;
- impl.schedulePause = sandbox.spy();
- impl.vsync_ = {
- mutate(callback) {
- callback();
- },
- };
- sandbox.stub(timer, 'delay', function(callback) {
- callback();
- });
- expect(sidebarElement.hasAttribute('open')).to.be.false;
- impl.open_();
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- const eventObj = document.createEventObject ?
- document.createEventObject() : document.createEvent('Events');
- if (eventObj.initEvent) {
- eventObj.initEvent('click', true, true);
- }
- li.dispatchEvent ?
- li.dispatchEvent(eventObj) :
- li.fireEvent('onkeydown', eventObj);
- expect(sidebarElement.hasAttribute('open')).to.be.true;
- expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
- expect(sidebarElement.style.display).to.equal('');
- expect(impl.schedulePause).to.have.not.been.called;
- });
- });
-
- // Tests for amp-sidebar 1.0
- it('should not create toolbars without ', () => {
- return getAmpSidebar().then(obj => {
- const sidebarElement = obj.ampSidebar;
- const headerElements = sidebarElement.ownerDocument
- .getElementsByTagName('header');
- const toolbarElements = sidebarElement.ownerDocument
- .querySelectorAll('[toolbar]');
- expect(headerElements.length).to.be.equal(0);
- expect(toolbarElements.length).to.be.equal(0);
- expect(sidebarElement.implementation_.toolbars_.length).to.be.equal(0);
- });
- });
-
- it('should create a toolbar element within the toolbar-target', () => {
- return getAmpSidebar({
- toolbars: [{}],
- }).then(obj => {
- const sidebarElement = obj.ampSidebar;
- expect(sidebarElement.implementation_.toolbars_.length)
- .to.be.equal(1);
- });
- });
-
- it('should create multiple toolbar elements, \
- within their respective containers', () => {
- return getAmpSidebar({
- toolbars: [{},
- {
- media: '(min-width: 1024px)',
- },
- ],
- }).then(obj => {
- const sidebarElement = obj.ampSidebar;
- expect(sidebarElement.implementation_.toolbars_.length)
- .to.be.equal(2);
- });
- });
- });
- });
+import {KeyCodes} from '../../../../src/utils/key-codes';
+import {Services} from '../../../../src/services';
+import {assertScreenReaderElement} from '../../../../testing/test-helper';
+import {toggleExperiment} from '../../../../src/experiments';
+import '../amp-sidebar';
+
+
+describes.realWin('amp-sidebar 1.0 version', {
+ win: { /* window spec */
+ location: '...',
+ historyOff: false,
+ },
+ amp: { /* amp spec */
+ runtimeOn: false,
+ extensions: ['amp-sidebar:1.0'],
+ },
+}, env => {
+ let win, doc;
+ let platform;
+ let timer;
+
+ beforeEach(() => {
+ win = env.win;
+ doc = win.document;
+ platform = Services.platformFor(win);
+ timer = Services.timerFor(win);
+ });
+
+ describe('amp-sidebar', () => {
+
+ function getAmpSidebar(options) {
+ options = options || {};
+ const ampSidebar = doc.createElement('amp-sidebar');
+ const list = doc.createElement('ul');
+ for (let i = 0; i < 10; i++) {
+ const li = doc.createElement('li');
+ li.innerHTML = 'Menu item ' + i;
+ list.appendChild(li);
+ }
+ ampSidebar.appendChild(list);
+ const anchor = doc.createElement('a');
+ anchor.href = '#section1';
+ ampSidebar.appendChild(anchor);
+ if (options.toolbars) {
+ // Stub our sidebar operations, doing this here as it will
+ // Ease testing our media queries
+ const impl = ampSidebar.implementation_;
+ sandbox.stub(impl.vsync_,
+ 'mutate', callback => {
+ callback();
+ });
+ sandbox.stub(impl.vsync_,
+ 'mutatePromise', callback => {
+ callback();
+ return Promise.resolve();
+ });
+ // Create our individual toolbars
+ options.toolbars.forEach(toolbarObj => {
+ const navToolbar = doc.createElement('nav');
+
+ //Create/Set toolbar-target
+ const toolbarTarget = doc.createElement('div');
+ if (toolbarObj.toolbarTarget) {
+ toolbarTarget.setAttribute('id',
+ toolbarObj.toolbarTarget);
+ navToolbar.setAttribute('toolbar-target',
+ toolbarObj.toolbarTarget);
+ } else {
+ toolbarTarget.setAttribute('id', 'toolbar-target');
+ navToolbar.setAttribute('toolbar-target', 'toolbar-target');
+ }
+ doc.body.appendChild(toolbarTarget);
+
+ // Set the toolbar media
+ if (toolbarObj.media) {
+ navToolbar.setAttribute('toolbar', toolbarObj.media);
+ } else {
+ navToolbar.setAttribute('toolbar', '(min-width: 768px)');
+ }
+ const toolbarList = doc.createElement('ul');
+ for (let i = 0; i < 3; i++) {
+ const li = doc.createElement('li');
+ li.innerHTML = 'Toolbar item ' + i;
+ toolbarList.appendChild(li);
+ }
+ navToolbar.appendChild(toolbarList);
+ ampSidebar.appendChild(navToolbar);
+ });
+ }
+ if (options.side) {
+ ampSidebar.setAttribute('side', options.side);
+ }
+ if (options.open) {
+ ampSidebar.setAttribute('open', '');
+ }
+ if (options.closeText) {
+ ampSidebar.setAttribute('data-close-button-aria-label',
+ options.closeText);
+ };
+ ampSidebar.setAttribute('id', 'sidebar1');
+ ampSidebar.setAttribute('layout', 'nodisplay');
+ doc.body.appendChild(ampSidebar);
+ return ampSidebar.build().then(() => {
+ return ampSidebar.layoutCallback();
+ }).then(() => {
+ if (options.toolbars) {
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ }
+ return ampSidebar;
+ });
+ }
+
+ beforeEach(() => {
+ toggleExperiment(win, 'amp-sidebar 1.0', true);
+ });
+
+ it('should replace text to screen reader \
+ button in data-close-button-aria-label', () => {
+ return getAmpSidebar({'closeText':
+ 'data-close-button-aria-label'}).then(sidebarElement => {
+ const closeButton = sidebarElement.lastElementChild;
+ expect(closeButton.textContent)
+ .to.equal('data-close-button-aria-label');
+ });
+ });
+
+ it('should open from left is side is not specified', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ expect(sidebarElement.getAttribute('side')).to.equal('left');
+ });
+ });
+
+ it('should open from right is side right is specified', () => {
+ return getAmpSidebar({'side': 'right'}).then(sidebarElement => {
+ expect(sidebarElement.getAttribute('side')).to.equal('right');
+ });
+ });
+
+ it('should create mask element in DOM', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ impl.open_();
+ expect(doc.querySelectorAll('.i-amphtml-sidebar-mask').length)
+ .to.equal(1);
+ });
+ });
+
+ it('should create an invisible close \
+ button for screen readers only', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.close_ = sandbox.spy();
+ const closeButton = sidebarElement.lastElementChild;
+ expect(closeButton).to.exist;
+ expect(closeButton.tagName).to.equal('BUTTON');
+ assertScreenReaderElement(closeButton);
+ expect(closeButton.textContent).to.equal('Close the sidebar');
+ expect(impl.close_).to.have.not.been.called;
+ closeButton.click();
+ expect(impl.close_).to.be.calledOnce;
+ });
+ });
+
+ it('should open sidebar on button click', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ const historyPushSpy = sandbox.spy();
+ const historyPopSpy = sandbox.spy();
+ impl.scheduleLayout = sandbox.spy();
+ impl.getHistory_ = function() {
+ return {
+ push() {
+ historyPushSpy();
+ return Promise.resolve(11);
+ },
+ pop() {
+ historyPopSpy();
+ return Promise.resolve(11);
+ },
+ };
+ };
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ timer.cancel = sandbox.spy();
+ impl.openOrCloseTimeOut_ = 10;
+
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ expect(sidebarElement.getAttribute('role')).to.equal('menu');
+ expect(doc.activeElement).to.equal(sidebarElement);
+ expect(sidebarElement.style.display).to.equal('');
+ expect(timer.cancel).to.be.calledOnce;
+ expect(impl.scheduleLayout).to.be.calledOnce;
+ expect(historyPushSpy).to.be.calledOnce;
+ expect(historyPopSpy).to.have.not.been.called;
+ expect(impl.historyId_).to.not.equal('-1');
+
+ // second call to open_() should be a no-op and not increase call counts.
+ impl.open_();
+ expect(impl.scheduleLayout).to.be.calledOnce;
+ expect(historyPushSpy).to.be.calledOnce;
+ expect(historyPopSpy).to.have.not.been.called;
+
+ });
+ });
+
+ it('should close sidebar on button click', () => {
+ return getAmpSidebar({'open': true}).then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ const historyPushSpy = sandbox.spy();
+ const historyPopSpy = sandbox.spy();
+ impl.scheduleLayout = sandbox.spy();
+ impl.getHistory_ = function() {
+ return {
+ push() {
+ historyPushSpy();
+ return Promise.resolve(11);
+ },
+ pop() {
+ historyPopSpy();
+ return Promise.resolve(11);
+ },
+ };
+ };
+ impl.historyId_ = 100;
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+
+ timer.cancel = sandbox.spy();
+ impl.openOrCloseTimeOut_ = 10;
+ impl.close_();
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
+ expect(sidebarElement.style.display).to.equal('none');
+ expect(timer.cancel).to.be.calledOnce;
+ expect(impl.schedulePause).to.be.calledOnce;
+ expect(historyPopSpy).to.be.calledOnce;
+ expect(impl.historyId_).to.equal(-1);
+
+ // second call to close_() should be a no-op and not increase call counts.
+ impl.close_();
+ expect(impl.schedulePause).to.be.calledOnce;
+ expect(historyPopSpy).to.be.calledOnce;
+ });
+ });
+
+ it('should toggle sidebar on button click', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.scheduleLayout = sandbox.spy();
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
+ expect(sidebarElement.getAttribute('role')).to.equal('menu');
+ expect(doc.activeElement).to.not.equal(sidebarElement);
+ impl.toggle_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ expect(doc.activeElement).to.equal(sidebarElement);
+ expect(sidebarElement.style.display).to.equal('');
+ expect(impl.scheduleLayout).to.be.calledOnce;
+ impl.toggle_();
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
+ expect(sidebarElement.style.display).to.equal('none');
+ expect(impl.schedulePause).to.be.calledOnce;
+ });
+ });
+
+ it('should close sidebar on escape', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
+ if (eventObj.initEvent) {
+ eventObj.initEvent('keydown', true, true);
+ }
+ eventObj.keyCode = KeyCodes.ESCAPE;
+ eventObj.which = KeyCodes.ESCAPE;
+ const el = doc.documentElement;
+ el.dispatchEvent ?
+ el.dispatchEvent(eventObj) : el.fireEvent('onkeydown', eventObj);
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
+ expect(sidebarElement.style.display).to.equal('none');
+ expect(impl.schedulePause).to.be.calledOnce;
+ });
+ });
+
+ it('should reflect state of the sidebar', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.scheduleResume = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(impl.isOpen_()).to.be.false;
+ expect(impl.schedulePause).to.have.not.been.called;
+ expect(impl.scheduleResume).to.have.not.been.called;
+ impl.toggle_();
+ expect(impl.isOpen_()).to.be.true;
+ expect(impl.schedulePause).to.have.not.been.called;
+ expect(impl.scheduleResume).to.be.calledOnce;
+ impl.toggle_();
+ expect(impl.isOpen_()).to.be.false;
+ expect(impl.schedulePause).to.be.calledOnce;
+ expect(impl.scheduleResume).to.be.calledOnce;
+ impl.toggle_();
+ expect(impl.isOpen_()).to.be.true;
+ expect(impl.schedulePause).to.be.calledOnce;
+ expect(impl.scheduleResume).to.have.callCount(2);
+ impl.toggle_();
+ expect(impl.isOpen_()).to.be.false;
+ expect(impl.schedulePause).to.have.callCount(2);
+ expect(impl.scheduleResume).to.have.callCount(2);
+ });
+ });
+
+ it.skip('should fix scroll leaks on ios safari', () => {
+ sandbox.stub(platform, 'isIos').returns(true);
+ sandbox.stub(platform, 'isSafari').returns(true);
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ const scrollLeakSpy = sandbox.spy(impl, 'fixIosElasticScrollLeak_');
+ impl.buildCallback();
+ expect(scrollLeakSpy).to.be.calledOnce;
+ });
+ });
+
+ it.skip('should adjust for IOS safari bottom bar', () => {
+ sandbox.stub(platform, 'isIos').returns(true);
+ sandbox.stub(platform, 'isSafari').returns(true);
+ return getAmpSidebar().then(sidebarElement => {
+ const impl = sidebarElement.implementation_;
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ const compensateIosBottombarSpy =
+ sandbox.spy(impl, 'compensateIosBottombar_');
+ const initalChildrenCount = sidebarElement.children.length;
+ impl.open_();
+ expect(compensateIosBottombarSpy).to.be.calledOnce;
+ // 10 lis + one top padding element inserted
+ expect(sidebarElement.children.length)
+ .to.equal(initalChildrenCount + 1);
+ });
+ });
+
+ it('should close sidebar if clicked on a non-local anchor', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const anchor = sidebarElement.getElementsByTagName('a')[0];
+ anchor.href = '#newloc';
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
+ if (eventObj.initEvent) {
+ eventObj.initEvent('click', true, true);
+ }
+ sandbox.stub(sidebarElement, 'getAmpDoc', () => {
+ return {
+ win: {
+ location: {
+ href: window.location.href,
+ },
+ },
+ };
+ });
+ anchor.dispatchEvent ?
+ anchor.dispatchEvent(eventObj) :
+ anchor.fireEvent('onkeydown', eventObj);
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('true');
+ expect(sidebarElement.style.display).to.equal('none');
+ expect(impl.schedulePause).to.be.calledOnce;
+ });
+ });
+
+ it('should not close sidebar if \
+ clicked on a new origin navigation', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const anchor = sidebarElement.getElementsByTagName('a')[0];
+ anchor.href = '#newloc';
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
+ if (eventObj.initEvent) {
+ eventObj.initEvent('click', true, true);
+ }
+ sandbox.stub(sidebarElement, 'getAmpDoc', () => {
+ return {
+ win: {
+ location: {
+ // Mocking navigating from example.com -> localhost:9876
+ href: 'http://example.com',
+ },
+ },
+ };
+ });
+ anchor.dispatchEvent ?
+ anchor.dispatchEvent(eventObj) :
+ anchor.fireEvent('onkeydown', eventObj);
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ expect(sidebarElement.style.display).to.equal('');
+ expect(impl.schedulePause).to.have.not.been.called;
+ });
+ });
+
+ it('should not close sidebar if clicked on new page navigation', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const anchor = sidebarElement.getElementsByTagName('a')[0];
+ anchor.href = '#newloc';
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
+ if (eventObj.initEvent) {
+ eventObj.initEvent('click', true, true);
+ }
+ sandbox.stub(sidebarElement, 'getAmpDoc', () => {
+ return {
+ win: {
+ location: {
+ // Mocking navigating from
+ // /context.html?old=context -> /context.html
+ href: 'http://localhost:9876/context.html?old=context',
+ },
+ },
+ };
+ });
+ anchor.dispatchEvent ?
+ anchor.dispatchEvent(eventObj) :
+ anchor.fireEvent('onkeydown', eventObj);
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ expect(sidebarElement.style.display).to.equal('');
+ expect(impl.schedulePause).to.have.not.been.called;
+ });
+ });
+
+ it('should not close sidebar if clicked on non-anchor', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const li = sidebarElement.getElementsByTagName('li')[0];
+ const impl = sidebarElement.implementation_;
+ impl.schedulePause = sandbox.spy();
+ impl.vsync_ = {
+ mutate(callback) {
+ callback();
+ },
+ };
+ sandbox.stub(timer, 'delay', function(callback) {
+ callback();
+ });
+ expect(sidebarElement.hasAttribute('open')).to.be.false;
+ impl.open_();
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ const eventObj = doc.createEventObject ?
+ doc.createEventObject() : doc.createEvent('Events');
+ if (eventObj.initEvent) {
+ eventObj.initEvent('click', true, true);
+ }
+ li.dispatchEvent ?
+ li.dispatchEvent(eventObj) :
+ li.fireEvent('onkeydown', eventObj);
+ expect(sidebarElement.hasAttribute('open')).to.be.true;
+ expect(sidebarElement.getAttribute('aria-hidden')).to.equal('false');
+ expect(sidebarElement.style.display).to.equal('');
+ expect(impl.schedulePause).to.have.not.been.called;
+ });
+ });
+
+ // Tests for amp-sidebar 1.0
+ it('should not create toolbars without ', () => {
+ return getAmpSidebar().then(sidebarElement => {
+ const headerElements = doc.getElementsByTagName('header');
+ const toolbarElements = doc.querySelectorAll('[toolbar]');
+ expect(headerElements.length).to.be.equal(0);
+ expect(toolbarElements.length).to.be.equal(0);
+ expect(sidebarElement.implementation_.toolbars_.length).to.be.equal(0);
+ });
+ });
+
+ it('should create a toolbar element within the toolbar-target', () => {
+ return getAmpSidebar({
+ toolbars: [{}],
+ }).then(sidebarElement => {
+ expect(sidebarElement.implementation_.toolbars_.length)
+ .to.be.equal(1);
+ });
+ });
+
+ it('should create multiple toolbar elements, \
+ within their respective containers', () => {
+ return getAmpSidebar({
+ toolbars: [{},
+ {
+ media: '(min-width: 1024px)',
+ },
+ ],
+ }).then(sidebarElement => {
+ expect(sidebarElement.implementation_.toolbars_.length)
+ .to.be.equal(2);
+ });
+ });
+ });
+});
diff --git a/src/runtime.js b/src/runtime.js
index 15ae39d7b6cb..1d6e91fdfb6b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -83,7 +83,6 @@ import {
toggleExperiment,
} from './experiments';
import {parseUrl} from './url';
-import {registerElement} from './custom-element';
import {registerExtendedElement} from './extended-element';
import {setStyle} from './style';
import {waitForBody} from './dom';
@@ -96,8 +95,6 @@ setReportError(reportErrorForWin.bind(null, self));
/** @const @private {string} */
const TAG = 'runtime';
-/** @type {!Object} */
-const elementsForTesting = {};
/**
* Install runtime-level services.
@@ -487,13 +484,6 @@ function prepareAndRegisterElementShadowMode(global, extensions,
*/
function registerElementClass(global, name, implementationClass, opt_css) {
registerExtendedElement(global, name, implementationClass);
- if (getMode().test) {
- elementsForTesting[name] = {
- name,
- implementationClass,
- css: opt_css,
- };
- }
// Register this extension to resolve its Service Promise.
registerServiceBuilder(global, name, emptyService);
}
@@ -980,44 +970,6 @@ function emptyService() {
}
-/**
- * Registers all extended elements as normal elements in the given
- * window.
- * Make sure to call `adopt(window)` in your unit test as well and
- * then call this on the generated iframe.
- * @param {!Window} win
- */
-export function registerForUnitTest(win) {
- for (const key in elementsForTesting) {
- let element = null;
- element = elementsForTesting[key];
- if (element.css) {
- installStyles(win.document, element.css, () => {
- registerElement(win, element.name, element.implementationClass);
- }, false, element.name);
- } else {
- registerElement(win, element.name, element.implementationClass);
- }
- }
-}
-
-
-/**
- * Registers a specific element for testing.
- * @param {!Window} win
- * @param {string} elementName
- * @visibleForTesting
- */
-export function registerElementForTesting(win, elementName) {
- const element = elementsForTesting[elementName];
- if (!element) {
- throw new Error('test element not found: ' + elementName +
- '\nKnown elements ' + Object.keys(elementsForTesting).sort());
- }
- win.AMP.registerElement(element.name, element.implementationClass,
- element.css);
-}
-
/**
* For a given extension, checks that its version is the same
* as the version of the main AMP binary.
diff --git a/testing/describes.js b/testing/describes.js
index 3772bb7fe454..69dd0064b184 100644
--- a/testing/describes.js
+++ b/testing/describes.js
@@ -97,7 +97,6 @@ import {
adoptShadowMode,
installAmpdocServices,
installRuntimeServices,
- registerElementForTesting,
} from '../src/runtime';
import {createElementWithAttributes} from '../src/dom';
import {addParamsToUrl} from '../src/url';
@@ -687,8 +686,6 @@ class AmpFixture {
const installer = extensionsBuffer[`${extensionId}:${version}`];
if (installer) {
registerExtension(env.extensions, extensionId, installer, win.AMP);
- } else {
- registerElementForTesting(win, extensionId);
}
});
}
diff --git a/testing/iframe.js b/testing/iframe.js
index 34390189fe53..e09957431b2b 100644
--- a/testing/iframe.js
+++ b/testing/iframe.js
@@ -25,7 +25,6 @@ import {parseIfNeeded} from '../src/iframe-helper';
import {
installAmpdocServices,
installRuntimeServices,
- registerForUnitTest,
} from '../src/runtime';
import installCustomElements from
'document-register-element/build/document-register-element.node';
@@ -233,7 +232,6 @@ export function createIframePromise(opt_runtimeOff, opt_beforeLayoutCallback) {
installRuntimeServices(iframe.contentWindow);
installCustomElements(iframe.contentWindow);
installAmpdocServices(ampdoc);
- registerForUnitTest(iframe.contentWindow);
Services.resourcesForDoc(ampdoc).ampInitComplete();
// Act like no other elements were loaded by default.
installStyles(iframe.contentWindow.document, cssText, () => {
@@ -285,7 +283,6 @@ export function createServedIframe(src) {
win.AMP_TEST_IFRAME = true;
win.AMP_TEST = true;
installRuntimeServices(win);
- registerForUnitTest(win);
resolve({
win: win,
doc: win.document,