Skip to content

Commit

Permalink
[amp-sidebar 1.0] [Toolbar] Added Tests for Current Toolbar functiona…
Browse files Browse the repository at this point in the history
…lity (#10084)

* Updated tests to use our toolbar class

* Got expects working in accordance with vsync window mutations

* Removed testing code from toolbar, and got media query testing working!

* Wrote tests for sidebar, covering as many individual functions as
possible

* Cleaned up tests, and added test for multiple toolbars

* Forgot to add a test for toolbar-only

* Seperated test files into correct lcoations

* Fixed linting errors

* Renamed toolbar test file

* Made toolbar more unit-testable

* Fixed wording on some test descriptions
  • Loading branch information
Aaron Turner authored and camelburrito committed Jun 26, 2017
1 parent 9286491 commit 40a7553
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 41 deletions.
5 changes: 4 additions & 1 deletion extensions/amp-sidebar/1.0/amp-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ export class AmpSidebar extends AMP.BaseElement {
.call(this.element.querySelectorAll('nav[toolbar]'), 0);
toolbarElements.forEach(toolbarElement => {
try {
this.toolbars_.push(new Toolbar(toolbarElement, this, this.vsync_));
const toolbar = new Toolbar(toolbarElement, this.win, this.vsync_);
this.element.parentElement
.insertBefore(toolbar.build(), this.element);
this.toolbars_.push(toolbar);
} catch (e) {
user().error(TAG, 'Failed to instantiate toolbar', e);
}
Expand Down
67 changes: 45 additions & 22 deletions extensions/amp-sidebar/1.0/test/test-amp-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import '../amp-sidebar';

/** @const */
const TOOLBAR_MEDIA = '(min-width: 768px)';
const DEFAULT_TOOLBAR_MEDIA = '(min-width: 768px)';


adopt(window);
Expand Down Expand Up @@ -60,17 +60,32 @@
const anchor = iframe.doc.createElement('a');
anchor.href = '#section1';
ampSidebar.appendChild(anchor);
if (options.toolbar) {
const navToolbar = iframe.doc.createElement('nav');
navToolbar.setAttribute('toolbar', TOOLBAR_MEDIA);
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.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(() => {
const navToolbar = iframe.doc.createElement('nav');
navToolbar.setAttribute('toolbar', DEFAULT_TOOLBAR_MEDIA);
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);
Expand All @@ -86,6 +101,11 @@
ampSidebar.setAttribute('layout', 'nodisplay');
return iframe.addElement(ampSidebar).then(() => {
timer = timerFor(iframe.win);
if (options.toolbars) {
sandbox.stub(timer, 'delay', function(callback) {
callback();
});
}
return {iframe, ampSidebar};
});
});
Expand Down Expand Up @@ -585,36 +605,39 @@
.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 target element, \
containing the navigation toolbar element', () => {
return getAmpSidebar({
toolbar: true,
toolbars: [true],
}).then(obj => {
const sidebarElement = obj.ampSidebar;
const toolbarNavElements = Array.prototype
.slice.call(sidebarElement.ownerDocument
.querySelectorAll('nav[toolbar]'), 0);
expect(toolbarNavElements.length).to.be.above(1);
expect(sidebarElement.implementation_.toolbars_.length).to.be.equal(1);
});
});

it('toolbar header should be hidden for the const TOOLBAR_MEDIA', () => {
it('should create multiple toolbar target elements, \
containing the navigation toolbar element', () => {
return getAmpSidebar({
toolbar: true,
toolbars: [true,
{
media: '(min-width: 1024px)',
},
],
}).then(obj => {
const sidebarElement = obj.ampSidebar;
const toolbarNavElements = Array.prototype
.slice.call(sidebarElement.ownerDocument
.querySelectorAll('nav[toolbar]'), 0);
expect(toolbarNavElements.length).to.be.above(1);
expect(toolbarNavElements.some(navElement => {
if (navElement.parentElement.style.display == 'none') {
return true;
}
return false;
})).to.be.true;
expect(toolbarNavElements.length).to.be.equal(4);
expect(sidebarElement.implementation_.toolbars_.length).to.be.equal(2);
});
});
});
Expand Down
215 changes: 215 additions & 0 deletions extensions/amp-sidebar/1.0/test/test-toolbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@

/**
* Copyright 2017 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {adopt} from '../../../../src/runtime';
import {createIframePromise} from '../../../../testing/iframe';
import {timerFor, vsyncFor} from '../../../../src/services';
import * as sinon from 'sinon';
import {Toolbar} from '../toolbar';

/** @const */
const DEFAULT_TOOLBAR_MEDIA = '(min-width: 768px)';

/** @const */
const TOOLBAR_CLASS = 'i-amphtml-toolbar';


adopt(window);

describe('amp-sidebar - toolbar', () => {
let sandbox;
let timer;
let vsync;

function getToolbars(options) {
options = options || {};
return createIframePromise().then(iframe => {
const toolbarContainerElement = iframe.doc.createElement('div');
const toolbars = [];
iframe.win.document.body.appendChild(toolbarContainerElement);
vsync = vsyncFor(iframe.win);
timer = timerFor(iframe.win);
// Stub our toolbar operations, doing this here as it will
// Ease testing our media queries
sandbox.stub(vsync,
'mutate', callback => {
callback();
});
sandbox.stub(vsync,
'mutatePromise', callback => {
callback();
return Promise.resolve();
});
sandbox.stub(timer, 'delay', function(callback) {
callback();
});

// Create our individual toolbars
options.forEach(toolbarObj => {
const navToolbar = iframe.doc.createElement('nav');
if (toolbarObj.media) {
navToolbar.setAttribute('toolbar', toolbar.media);
} else {
navToolbar.setAttribute('toolbar', DEFAULT_TOOLBAR_MEDIA);
}
if (toolbarObj.toolbarOnlyOnNav) {
navToolbar.setAttribute('toolbar-only', '');
}
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);
toolbarContainerElement.appendChild(navToolbar);
const toolbar = new Toolbar(navToolbar, iframe.win, vsync);
toolbarContainerElement.appendChild(toolbar.build());
toolbars.push(toolbar);
});

return {iframe, toolbarContainerElement, toolbars};
});
}

function resizeIframeToWidth(iframeObject, width, callback) {
iframeObject.iframe.setAttribute('width', width);
// Force the browser to re-draw
iframeObject.win.innerWidth;
callback();
}

beforeEach(() => {
sandbox = sinon.sandbox.create();
});

afterEach(() => {
sandbox.restore();
});

it('toolbar header should be hidden for a \
non-matching window size for DEFAULT_TOOLBAR_MEDIA', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
const toolbarElements = Array.prototype
.slice.call(obj.toolbarContainerElement.ownerDocument
.getElementsByClassName(TOOLBAR_CLASS), 0);
resizeIframeToWidth(obj.iframe, '1px', () => {
expect(toolbarElements.length).to.be.above(0);
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
});
expect(toolbarElements[0].parentElement.style.display)
.to.be.equal('none');
});
});
});

it('toolbar header should be shown for a \
matching window size for DEFAULT_TOOLBAR_MEDIA', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
const toolbarElements = Array.prototype
.slice.call(obj.toolbarContainerElement
.getElementsByClassName(TOOLBAR_CLASS), 0);
resizeIframeToWidth(obj.iframe, '4000px', () => {
expect(toolbarElements.length).to.be.above(0);
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
});
expect(toolbarElements[0].parentElement.style.display)
.to.be.equal('');
});
});
});

it('should hide <nav toolbar> elements with toolbar-only, \
inside the sidebar, but not inside the toolbar, for a matching \
window size for DEFAULT_TOOLBAR_MEDIA', () => {
return getToolbars([{
toolbarOnlyOnNav: true,
}]).then(obj => {
const toolbars = obj.toolbars;
resizeIframeToWidth(obj.iframe, '4000px', () => {
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
});
const toolbarNavElements = Array.prototype
.slice.call(obj.toolbarContainerElement.ownerDocument
.querySelectorAll('nav[toolbar]'), 0);
const hiddenToolbarNavElements = Array.prototype
.slice.call(obj.toolbarContainerElement.ownerDocument
.querySelectorAll('nav[style]'), 0);
expect(toolbarNavElements.length).to.be.equal(2);
expect(hiddenToolbarNavElements.length).to.be.equal(1);
expect(toolbars.length).to.be.equal(1);
});
});
});

it('toolbar should be in the hidden state \
when it is not being displayed', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
resizeIframeToWidth(obj.iframe, '1px', () => {
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
expect(toolbar.isToolbarShown_()).to.be.false;
});
});
});
});

it('toolbar should be in the shown state \
when it is being displayed', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
resizeIframeToWidth(obj.iframe, '4000px', () => {
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
expect(toolbar.isToolbarShown_()).to.be.true;
});
});
});
});

it('toolbar should not be able to be shown \
if already in the shown state', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
resizeIframeToWidth(obj.iframe, '4000px', () => {
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
expect(toolbar.attemptShow_()).to.be.undefined;
});
});
});
});

it('toolbar should be able to be shown \
if not in the shown state, and return a promise', () => {
return getToolbars([{}]).then(obj => {
const toolbars = obj.toolbars;
resizeIframeToWidth(obj.iframe, '1px', () => {
toolbars.forEach(toolbar => {
toolbar.onLayoutChange();
expect(toolbar).to.exist;
});
});
});
});
});

0 comments on commit 40a7553

Please sign in to comment.