first commit

This commit is contained in:
armansansd
2023-07-12 16:31:19 +01:00
commit 3424b1927b
23306 changed files with 2217776 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
/* jslint mocha: true */
/*global describe, it, before, beforeEach, after, afterEach, $, Foundation */
describe('Abide', function() {
var plugin;
var $html;
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element & plugin options', function() {
$html = $('<form data-abide novalidate></form>').appendTo('body');
plugin = new Foundation.Abide($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
it('the options are recursively merged', function() {
$html = $('<form data-abide novalidate></form>').appendTo('body');
var options = {
validators: {
notEqualTo: function (el, required, parent) {
return $(`#${el.attr('data-equalto')}`).val() !== el.val();
}
}
};
plugin = new Foundation.Abide($html, options);
plugin.options.validators.should.includes.keys('equalTo', 'notEqualTo');
});
});
describe('validateInput()', function() {
it('returns true for hidden inputs', function() {
$html = $("<form data-abide novalidate><input type='hidden' required></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("input")).should.equal(true);
});
it('returns true for inputs with [data-abide-ignore]', function() {
$html = $("<form data-abide novalidate><input type='text' required data-abide-ignore></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("input")).should.equal(true);
});
it('returns true for checked checkboxes', function() {
$html = $("<form data-abide><input type='checkbox' required checked='checked'></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("input")).should.equal(true);
});
it('returns false for unchecked checkboxes', function() {
$html = $("<form data-abide><input type='checkbox' required></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("input")).should.equal(false);
});
it('returns true for selected select option', function() {
$html = $("<form data-abide><select required><option value=''></option><option value='One'>One</option><option value='Two' selected='selected'>Two</option></select></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("select")).should.equal(true);
$html.find("select").val().should.equal("Two");
});
it('returns false for unselected select option', function() {
$html = $("<form data-abide><select required><option value=''></option><option value='One'>One</option><option value='Two'>Two</option></select></form>").appendTo("body");
plugin = new Foundation.Abide($html, {});
plugin.validateInput($html.find("select")).should.equal(false);
});
});
describe('addErrorClasses()', function() {
it('adds aria-invalid attribute to element', function() {
$html = $('<form data-abide><input type="text"></form>').appendTo('body');
plugin = new Foundation.Abide($html, {});
plugin.addErrorClasses($html.find('input'));
$html.find('input').should.have.attr('aria-invalid', 'true')
});
});
describe('addGlobalErrorA11yAttributes()', function () {
it('adds [aria-live] attribute on element', function () {
$html = $(`<form data-abide><span data-abide-error></span></form>`).appendTo('body');
plugin = new Foundation.Abide($html, { a11yErrorLevel: 'test-level' });
plugin.addA11yAttributes($html.find('[data-abide-error]'));
$html.find('[data-abide-error]').should.have.attr('aria-live', 'test-level');
});
});
describe('addA11yAttributes()', function () {
it('adds [aria-describedby] attribute to field and [for] attribute to form error', function() {
$html = $(`
<form data-abide>
<input type="text" id="test-input">
<label class="form-error" id="test-error">Form error</label>
</form>
`).appendTo('body');
plugin = new Foundation.Abide($html, {});
plugin.addA11yAttributes($html.find('input'));
$html.find('input').should.have.attr('aria-describedby', 'test-error');
$html.find('label.form-error').should.have.attr('for', 'test-input');
});
it('adds attributes and ids when no id is set', function() {
$html = $(`
<form data-abide>
<input type="text">
<label class="form-error">Form error</label>
</form>
`).appendTo('body');
plugin = new Foundation.Abide($html, {});
plugin.addA11yAttributes($html.find('input'));
const errorId = $html.find('.form-error').attr('id');
$html.find('.form-error').should.have.attr('id').exist;
$html.find('input').should.have.attr('aria-describedby', errorId);
const inputId = $html.find('input').attr('id');
$html.find('input').should.have.attr('id').exist;
$html.find('.form-error').should.have.attr('for', inputId);
});
});
describe('removeErrorClasses()', function() {
it('removes aria-invalid attribute from element', function() {
$html = $('<form data-abide><input type="text"></form>').appendTo('body');
plugin = new Foundation.Abide($html, {});
// Add error classes first
plugin.addErrorClasses($html.find('input'));
plugin.removeErrorClasses($html.find('input'));
$html.find('input').should.not.have.attr('aria-invalid')
});
});
describe('removeRadioErrorClasses()', function() {
it('removes aria-invalid attribute from radio group', function() {
$html = $('<form data-abide><input type="radio" name="groupName"></form>').appendTo('body');
plugin = new Foundation.Abide($html, {});
// Add error classes first
plugin.addErrorClasses($html.find('input'));
plugin.removeRadioErrorClasses('groupName');
$html.find('input').should.not.have.attr('aria-invalid')
});
});
describe('resetForm()', function() {
it('removes aria-invalid attribute from elements', function() {
$html = $('<form data-abide><input type="text"></form>').appendTo('body');
plugin = new Foundation.Abide($html, {});
// Add error classes first
plugin.addErrorClasses($html.find('input'));
plugin.resetForm();
$html.find('input').should.not.have.attr('aria-invalid')
});
});
});
+190
View File
@@ -0,0 +1,190 @@
describe('Accordion', function() {
var plugin;
var $html;
var template = `<ul class="accordion" data-accordion>
<li class="accordion-item is-active" data-accordion-item>
<a href="#" class="accordion-title">Accordion 1</a>
<div class="accordion-content" data-tab-content >
<p>Panel 1. Lorem ipsum dolor</p>
<a href="#">Nowhere to Go</a>
</div>
</li>
<li class="accordion-item" data-accordion-item>
<a href="#" class="accordion-title">Accordion 2</a>
<div class="accordion-content" data-tab-content>
<textarea></textarea>
<button class="button">I do nothing!</button>
</div>
</li>
<li class="accordion-item" data-accordion-item>
<a href="#" class="accordion-title">Accordion 3</a>
<div class="accordion-content" data-tab-content>
Pick a date!
<input type="date"></input>
</div>
</li>
</ul>`;
afterEach(function() {
plugin.destroy();
document.activeElement.blur();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('up()', function(done) {
it('closes the targeted container if allowAllClosed is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {allowAllClosed: true});
plugin.up($html.find('.accordion-content').eq(0));
$html.find('.accordion-content').eq(0).should.have.attr('aria-hidden', 'true');
$html.on('up.zf.accordion', function() {
$html.find('.accordion-content').eq(0).should.be.hidden;
done();
});
});
it('toggles attributes of title of the targeted container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {allowAllClosed: true});
plugin.up($html.find('.accordion-content').eq(0));
$html.find('.accordion-title').eq(0).should.have.attr('aria-expanded', 'false');
$html.find('.accordion-title').eq(0).should.have.attr('aria-selected', 'false');
});
it('not closes the open container if allowAllClosed is false', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {allowAllClosed: false});
plugin.up($html.find('.accordion-content').eq(0));
$html.find('.accordion-content').eq(0).should.be.visible;
// Element has aria-hidden="false" not set if it has not been actively toggled so far
// Therefor check if it has not aria-hidden="true"
$html.find('.accordion-content').eq(0).should.not.have.attr('aria-hidden', 'true');
});
});
describe('down()', function() {
it('opens the targeted container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
plugin.down($html.find('.accordion-content').eq(1));
$html.find('.accordion-content').eq(1).should.be.visible;
$html.find('.accordion-content').eq(1).should.have.attr('aria-hidden', 'false');
});
it('toggles attributes of title of the targeted container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
plugin.down($html.find('.accordion-content').eq(1));
$html.find('.accordion-title').eq(1).should.have.attr('aria-expanded', 'true');
$html.find('.accordion-title').eq(1).should.have.attr('aria-selected', 'true');
});
it('closes open container if multiExpand is false', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {multiExpand: false});
plugin.down($html.find('.accordion-content').eq(1));
$html.find('.accordion-content').eq(0).should.have.attr('aria-hidden', 'true');
$html.on('up.zf.accordion', function() {
$html.find('.accordion-content').eq(0).should.be.hidden;
done();
});
});
it('not closes open container if multiExpand is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {multiExpand: true});
plugin.down($html.find('.accordion-content').eq(1));
$html.find('.accordion-content').eq(0).should.be.visible;
// Element has aria-hidden="false" not set if it has not been actively toggled so far
// Therefor check if it has not aria-hidden="true"
$html.find('.accordion-content').eq(0).should.not.have.attr('aria-hidden', 'true');
});
});
describe('toggle()', function(done) {
it('closes the only open container if allowAllClosed is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {allowAllClosed: true});
plugin.toggle($html.find('.accordion-content').eq(0));
$html.find('.accordion-content').eq(0).should.have.attr('aria-hidden', 'true');
$html.on('up.zf.accordion', function() {
$html.find('.accordion-content').eq(0).should.be.hidden;
done();
});
});
it('not closes the only open container if allowAllClosed is false', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {allowAllClosed: false});
plugin.toggle($html.find('.accordion-content').eq(0));
$html.find('.accordion-content').eq(0).should.be.visible;
$html.find('.accordion-content').eq(0).should.have.attr('aria-hidden', 'false');
});
});
describe('keyboard events', function() {
it('opens next panel on ARROW_DOWN', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
$html.find('.accordion-title').eq(0).focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
$html.find('.accordion-content').eq(1).should.be.visible;
$html.find('.accordion-content').eq(1).should.have.attr('aria-hidden', 'false');
// Check if focus was moved
$html.find('.accordion-title').eq(1)[0].should.be.equal(document.activeElement);
});
it('opens previous panel on ARROW_UP', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
$html.find('.accordion-title').eq(2).focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
$html.find('.accordion-content').eq(1).should.be.visible;
$html.find('.accordion-content').eq(1).should.have.attr('aria-hidden', 'false');
// Check if focus was moved
$html.find('.accordion-title').eq(1)[0].should.be.equal(document.activeElement);
});
it('opens related panel on ENTER', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
$html.find('.accordion-title').eq(1).focus()
.trigger(window.mockKeyboardEvent('ENTER'));
$html.find('.accordion-content').eq(1).should.be.visible;
$html.find('.accordion-content').eq(1).should.have.attr('aria-hidden', 'false');
});
it('opens related panel on SPACE', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Accordion($html, {});
$html.find('.accordion-title').eq(1).focus()
.trigger(window.mockKeyboardEvent('SPACE'));
$html.find('.accordion-content').eq(1).should.be.visible;
$html.find('.accordion-content').eq(1).should.have.attr('aria-hidden', 'false');
});
});
});
+190
View File
@@ -0,0 +1,190 @@
describe('Accordion Menu', function() {
var plugin;
var $html;
var template = `
<ul class="vertical menu">
<li>
<a href="#">Item 1</a>
<ul class="menu vertical nested">
<li>
<a href="#">Item 1A</a>
<ul class="menu vertical nested">
<li><a href="#">Item 1Ai</a></li>
<li><a href="#">Item 1Aii</a></li>
<li><a href="#">Item 1Aiii</a></li>
</ul>
</li>
<li><a href="#">Item 1B</a></li>
<li><a href="#">Item 1C</a></li>
</ul>
</li>
<li>
<a href="#">Item 2</a>
<ul class="menu vertical nested">
<li><a href="#">Item 2A</a></li>
<li><a href="#">Item 2B</a></li>
</ul>
</li>
<li><a href="#">Item 3</a></li>
</ul>`;
Foundation.AccordionMenu.defaults.slideSpeed = 0;
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('up()', function() {
it('closes the targeted submenu', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html);
const $submenu = $html.find('.is-accordion-submenu').eq(0);
// Open it first
plugin.down($submenu);
plugin.up($submenu);
setTimeout(() => {
// Should be hidden
$submenu.should.be.hidden;
// Should have attributes updated and without active classe
$submenu.should.have.attr('aria-hidden', 'true');
$submenu.should.not.have.class('is-active');
done();
}, 1);
});
it('toggles attributes of title of the targeted container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
// Open it first
plugin.down($html.find('.is-accordion-submenu').eq(0));
plugin.up($html.find('.is-accordion-submenu').eq(0));
$html.find('.is-accordion-submenu-parent').eq(0).should.have.attr('aria-expanded', 'false');
});
it('fires up.zf.accordionMenu event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {slideSpeed: 200});
// Open it first
plugin.down($html.find('.is-accordion-submenu').eq(0));
$html.on('up.zf.accordionMenu', function() {
$html.find('.is-accordion-submenu').eq(0).should.be.hidden;
done();
});
plugin.up($html.find('.is-accordion-submenu').eq(0));
});
});
describe('down()', function() {
it('opens the targeted submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
const $submenu = $html.find('.is-accordion-submenu').eq(0);
plugin.down($submenu);
// Should be visible
$submenu.should.be.visible;
// Should have attributes updated and with an active classe
$submenu.should.have.attr('aria-hidden', 'false');
$submenu.should.have.class('is-active');
});
it('toggles attributes of title of the targeted submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
plugin.down($html.find('.is-accordion-submenu').eq(0));
$html.find('.is-accordion-submenu-parent').eq(0).should.have.attr('aria-expanded', 'true');
});
it('closes open submenu if multiOpen is false', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {multiOpen: false});
// Open another one first
plugin.down($html.find('.is-accordion-submenu').eq(0));
plugin.down($html.find('.is-accordion-submenu').eq(2));
$html.find('.is-accordion-submenu').eq(0).should.be.hidden;
});
it('not closes open submenu if multiOpen is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {multiOpen: true});
// Open another one first
plugin.down($html.find('.is-accordion-submenu').eq(0));
plugin.down($html.find('.is-accordion-submenu').eq(2));
$html.find('.is-accordion-submenu').eq(0).should.be.visible;
});
it('fires down.zf.accordionMenu event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {slideSpeed: 200});
$html.on('down.zf.accordionMenu', function() {
$html.find('.is-accordion-submenu').eq(0).should.be.visible;
done();
});
plugin.down($html.find('.is-accordion-submenu').eq(0));
});
});
describe('toggle()', function() {
it('opens a closed container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
plugin.toggle($html.find('.is-accordion-submenu').eq(0));
$html.find('.is-accordion-submenu').eq(0).should.be.visible;
});
it('closes an open container', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
// Open first
plugin.down($html.find('.is-accordion-submenu').eq(0));
plugin.toggle($html.find('.is-accordion-submenu').eq(0));
$html.find('.is-accordion-submenu').eq(0).should.be.hidden;
});
});
describe('hideAll()', function() {
it('closes all accordions', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.AccordionMenu($html, {});
// Open some first
plugin.down($html.find('.is-accordion-submenu').eq(0));
plugin.down($html.find('.is-accordion-submenu').eq(1));
plugin.down($html.find('.is-accordion-submenu').eq(2));
plugin.hideAll();
$html.find('[data-submenu]').each(function() {
$(this).should.be.hidden;
});
});
});
});
+391
View File
@@ -0,0 +1,391 @@
describe('Drilldown Menu', function() {
var plugin;
var $html;
var template = `<ul class="menu" data-drilldown style="width: 200px" id="m1">
<li>
<a href="#">Item 1</a>
<ul id="Menu-1" class="menu">
<li>
<a href="#">Item 1A</a>
<ul id="Menu-1A" class="menu">
<li><a href="#Item-1Aa">Item 1Aa</a></li>
</ul>
</li>
<li><a href="#Item-1B">Item 1B</a></li>
<li><a href="#Item-1C">Item 1C</a></li>
</ul>
</li>
<li>
<a href="#">Item 2</a>
<ul id="Menu-2" class="menu">
<li><a href="#Item-2A">Item 2A</a></li>
<li><a href="#Item-2B">Item 2B</a></li>
</ul>
</li>
<li><a href="#Item-3"> Item 3</a></li>
</ul>`;
var templateWithToggler = `
<div>
<button id="trigger" data-toggle="target" type="button">Toggler</button>
<div id="target" class="is-hidden" data-toggler="is-hidden">
${template}
</div>
</div>
`;
afterEach(function() {
plugin.destroy();
document.activeElement.blur();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('stores additional elements', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
plugin.$submenuAnchors.should.be.an('object');
plugin.$submenus.should.be.an('object');
plugin.$menuItems.should.be.an('object');
});
});
describe('prepareMenu()', function() {
it('wraps the submenus', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
});
it('adds ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
plugin.$element.should.have.attr('role', 'tree');
plugin.$element.find('[data-submenu]').each(function() {
$(this).should.have.attr('role', 'group');
$(this).should.have.attr('aria-hidden', 'true');
});
plugin.$element.find('.is-drilldown-submenu-parent').each(function() {
$(this).should.have.attr('aria-haspopup', 'true');
$(this).should.have.attr('aria-expanded', 'false');
$(this).should.have.attr('aria-label', $(this).children('a').first().text());
});
plugin.$element.find('li:not(.js-drilldown-back)').each(function() {
$(this).should.have.attr('role', 'treeitem');
});
});
});
describe('show()', function() {
it('shows the given submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(0).find('ul').should.have.class('is-active');
});
it('toggles ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
$html.find('li.is-drilldown-submenu-parent').eq(0).should.have.attr('aria-expanded', 'true');
$html.find('li.is-drilldown-submenu-parent').eq(0).children('ul').should.have.attr('aria-hidden', 'false');
});
it('fires open.zf.drilldown event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.on('open.zf.drilldown', function() {
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(0).find('ul').should.have.class('is-active');
done();
});
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
});
});
describe('hide()', function() {
it('hides the given submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open it first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
plugin._hide($html.find('li.is-drilldown-submenu-parent').eq(0).children('ul'));
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(0).children('ul').should.have.class('is-closing');
});
it('toggles ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open it first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
plugin._hide($html.find('li.is-drilldown-submenu-parent').eq(0).children('ul'));
$html.find('li.is-drilldown-submenu-parent').eq(0).should.have.attr('aria-expanded', 'false');
$html.find('li.is-drilldown-submenu-parent').eq(0).children('ul').should.have.attr('aria-hidden', 'true');
});
it('fires hide.zf.drilldown event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open it first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(0));
$html.on('hide.zf.drilldown', function() {
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(0).children('ul').should.have.class('is-closing');
done();
});
plugin._hide($html.find('li.is-drilldown-submenu-parent').eq(0).children('ul'));
});
});
describe('hideAll()', function() {
it('hides all submenus', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open one first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(2));
plugin._hideAll();
$html.find('ul[data-submenu].is-active').each(function() {
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$(this).should.have.class('is-closing');
});
});
it('fires closed.zf.drilldown event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open one first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(2));
$html.one('closed.zf.drilldown', function() {
$html.find('ul[data-submenu].is-active').each(function() {
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$(this).should.have.class('is-closing');
});
done();
});
plugin._hideAll();
});
});
describe('back()', function() {
it('hides current submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open one first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(1));
$html.find('li.is-drilldown-submenu-parent').eq(1).children('ul').children('.js-drilldown-back').trigger('click');
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(1).children('ul').should.have.class('is-closing');
});
it('shows parent submenu', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open one first
plugin._show($html.find('li.is-drilldown-submenu-parent').eq(1));
$html.find('li.is-drilldown-submenu-parent').eq(1).children('ul').children('.js-drilldown-back').trigger('click');
// Checking with .be.hidden is not possible because they don't have display: block but z-index: -1
$html.find('li.is-drilldown-submenu-parent').eq(0).children('ul').should.have.class('is-active');
});
});
describe('toggle events', function () {
var $trigger, $target, $wrapper, togglerPlugin;
beforeEach(function () {
$html = $(templateWithToggler).appendTo('body');
$trigger = $html.find('#trigger');
$target = $html.find('#target');
$target = $html.find('#target');
togglerPlugin = new Foundation.Toggler($target, {});
plugin = new Foundation.Drilldown($html.find('[data-drilldown]'), { autoHeight: true });
$wrapper = $html.find('.is-drilldown');
});
it('correctly resize when opened', function () {
// Open the Drilldown
$trigger.focus().trigger('click');
// 3 items (including the back button) is around 115px height
$wrapper.height().should.be.within(110, 120);
});
it('correctly resize when closed', function () {
// Open then close the Drilldown
$trigger.focus().trigger('click');
$trigger.focus().trigger('click');
$wrapper.height().should.be.equal(0);
});
it('correctly resize when reopened on a submenu', function () {
// Open the Drilldown
$trigger.focus().trigger('click');
// Show a submenu with a smaller height
plugin._showMenu($html.find('#Menu-1A'));
// Close then reopen the the Drilldown
$trigger.focus().trigger('click');
$trigger.focus().trigger('click');
// 2 items (including the back button) is around 75px height
$wrapper.height().should.be.within(70, 80);
});
afterEach(function () {
togglerPlugin.destroy();
});
});
describe('keyboard events', function() {
// Currently not testable, as triggered event won't move on focus
it.skip('does not trap focus on root element going down', function() {
$html = $(template).appendTo('body');
let $dummyElement = $('<a tabindex="0">Dummy</a>').appendTo('body'); // Dummy target to see if focus is not trapped
plugin = new Foundation.Drilldown($html, {});
// Focus last element
$dummyElement.focus();
$html.find('> li:last-child > a').trigger(window.mockKeyboardEvent('TAB'));
document.activeElement.should.not.be.equal($html.find('> li:last-child > a')[0]);
$dummyElement.remove();
});
// Currently not testable, as triggered event won't move on focus
it.skip('does not trap focus on root element going up', function() {
let $dummyElement = $('<a tabindex="0">Dummy</a>').appendTo('body'); // Dummy target to see if focus is not trapped
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Focus first element
$dummyElement.focus();
$html.find('> li:first-child > a').trigger(window.mockKeyboardEvent('TAB', {shift: true}));
document.activeElement.should.not.be.equal($html.find('> li:first-child > a')[0]);
$dummyElement.remove();
});
it('closes current sub menu using ESC', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open it first
plugin._show($html.find('> li:nth-child(1)'))
$html.find('> li:nth-child(1) > ul > li:first-child > a').focus()
.trigger(window.mockKeyboardEvent('ESCAPE'));
$html.find('> li:nth-child(1) > ul').should.have.class('is-closing');
});
it('moves focus to next element on TAB', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('TAB'));
document.activeElement.should.be.equal($html.find('> li:nth-child(2) > a')[0]);
});
it('moves focus to previous element on TAB', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.find('> li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('TAB', {shift: true}));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > a')[0]);
});
it('moves focus to next element on ARROW_DOWN', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
document.activeElement.should.be.equal($html.find('> li:nth-child(2) > a')[0]);
});
it('moves focus to previous element on ARROW_UP', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.find('> li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > a')[0]);
});
it('opens child element on ARROW_RIGHT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
$html.find('> li:nth-child(1) > ul').should.have.class('is-active');
});
it('focuses parent link if parentLink is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {parentLink: true});
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
setTimeout(function() { // Timeout to make sure transition has ended
$html.find('> li:nth-child(1) > ul > li[data-is-parent-link] a')[0].should.be.equal(document.activeElement);
done();
}, 500);
});
it('closes child element on ARROW_LEFT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Drilldown($html, {});
// Open it first
plugin._show($html.find('> li:nth-child(1)'))
$html.find('> li:nth-child(1) > ul > li:first-child > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT'));
$html.find('> li:nth-child(1) > ul').should.have.class('is-closing');
});
});
});
+216
View File
@@ -0,0 +1,216 @@
describe('Dropdown', function() {
let plugin;
let $dropdownController;
let $dropdownContainer;
const getDropdownController = (buttonClasses = '') =>
`<button class="${buttonClasses}" type="button" data-toggle="my-dropdown">toggle</button>`;
const getDropdownContainer = (dropdownClasses = '') =>
`<div class="${dropdownClasses}" data-dropdown id="my-dropdown">Dropdown</div>`;
const getFocusableDropdownContainer = (dropdownClasses = '', inputId = '') =>
`<div class="${dropdownClasses}" data-dropdown id="my-dropdown">Dropdown${getFocusableInput(inputId)}</div>`;
const getFocusableInput = (inputId = '') =>
`<input type="text" placeholder="should auto focus" id="${inputId}" />`;
const getAutoFocusDropdownContainer = (dropdownClasses = '', inputId = '') =>
`<div class="${dropdownClasses}" data-dropdown data-auto-focus="true" id="my-dropdown">Dropdown${getFocusableInput(inputId)}</div>`;
afterEach(function() {
plugin.destroy();
document.activeElement.blur();
$dropdownController.remove();
$dropdownContainer.remove();
});
describe('constructor()', function() {
it('stores the element & plugin options', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('open()', function () {
it('fires show.zf.dropdown event', function () {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
let spy = sinon.spy();
$dropdownContainer.on('show.zf.dropdown', spy);
plugin.open();
sinon.assert.called(spy);
});
it('make the dropdown visible', function (done) {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
$dropdownContainer.on('show.zf.dropdown', function () {
$('#my-dropdown').should.not.be.hidden;
$('#my-dropdown').should.have.attr('aria-hidden', 'false');
$('#my-dropdown').should.have.class('is-open');
done();
});
plugin.open();
});
it('traps focus accoding to trapFocus option', function () {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, { trapFocus: true });
let spy = sinon.spy(Foundation.Keyboard, 'trapFocus');
plugin.open();
sinon.assert.called(spy);
Foundation.Keyboard.trapFocus.restore();
});
it('should autofocus according to autoFocus option', function(done) {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getAutoFocusDropdownContainer('', 'inputToFocus')).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, { autoFocus: true });
$dropdownContainer.on('show.zf.dropdown', function() {
document.activeElement.id.should.be.equal('inputToFocus');
done();
});
plugin.open();
});
});
describe('close()', function() {
it('releases focus if trapFocus option is true', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {trapFocus: true});
// Open it first...
plugin.open();
let spy = sinon.spy(Foundation.Keyboard, 'releaseFocus');
plugin.close();
sinon.assert.called(spy);
Foundation.Keyboard.releaseFocus.restore();
});
});
describe('inferred positioning', function() {
it('default orientation should be bottom', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
plugin.open()
plugin.position.should.equal('bottom');
});
it('gets right alignment from float-right', function() {
$dropdownController = $(getDropdownController('custom-style-before float-right custom-style-after'))
.appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
plugin.open()
plugin.position.should.equal('bottom')
plugin.alignment.should.equal('right')
});
});
describe('closeOnClick option', function() {
it('not closes a dropdown by clicking on the dropdown if closeOnClick option is true', function(done) {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {closeOnClick: true});
// Open it first...
plugin.open();
let spy = sinon.spy(plugin, 'close');
plugin.$element.trigger('click');
setTimeout(() => {
sinon.assert.notCalled(spy);
done();
}, 0);
});
});
describe('mouse events', function() {
it('opens the dropdown on button click', function(done) {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
let spy = sinon.spy(plugin, 'open');
$dropdownController.trigger('click');
setTimeout(() => {
sinon.assert.called(spy);
done();
}, 0);
});
it('opens the dropdown on button hover', function(done) {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, { hover: true, hoverDelay: 42 });
let spy = sinon.spy(plugin, 'open');
$dropdownController.trigger('mouseenter');
setTimeout(() => {
sinon.assert.called(spy);
done();
}, 42);
});
});
describe('keyboard events', function () {
it('opens Dropdown on SPACE', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
$dropdownController.focus()
.trigger(window.mockKeyboardEvent('SPACE'));
$dropdownContainer.should.be.visible;
});
it('does not focus Dropdown on SPACE by default', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
$dropdownController.focus()
.trigger(window.mockKeyboardEvent('SPACE'));
document.activeElement.should.be.equal($dropdownController[0]);
});
it('focuses Dropdown on SPACE when container has a focusable element', function() {
$dropdownController = $(getDropdownController()).appendTo('body');
$dropdownContainer = $(getFocusableDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
$dropdownController.focus()
.trigger(window.mockKeyboardEvent('SPACE'));
document.activeElement.should.be.equal($dropdownController[0]);
});
it('does not focus Dropdown when anchor is an input', function() {
$dropdownController = $('<input type="text" data-toggle="my-dropdown">').appendTo('body');
$dropdownContainer = $(getDropdownContainer()).appendTo('body');
plugin = new Foundation.Dropdown($dropdownContainer, {});
$dropdownController.focus()
.trigger(window.mockKeyboardEvent('SPACE'));
document.activeElement.should.be.equal($dropdownController[0]);
});
})
});
+205
View File
@@ -0,0 +1,205 @@
describe('Dropdown Menu', function () {
var plugin;
var $html;
var template = `<ul class="dropdown menu" data-dropdown-menu>
<li>
<a href="#Item-1">Item 1</a>
<ul class="menu">
<li><a href="#Item-1A">Item 1A</a></li>
<li>
<a href="#Item-1B">Item 1B</a>
<ul class="menu">
<li><a href="#Item-1Bi">Item 1B i</a></li>
<li><a href="#Item-1Bii">Item 1B ii</a></li>
<li>
<a href="#Item-1Biii">Item 1B iii</a>
<ul class="menu">
<li><a href="#Item-1Biiialpha">Item 1B iii alpha</a></li>
<li><a href="#Item-1Biiiomega">Item 1B iii omega</a></li>
</ul>
</li>
<li>
<a href="#Item-1Biv">Item 1B iv</a>
<ul class="menu">
<li><a href="#Item-1Bivalpha">Item 1B iv alpha</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#Item-1C">Item 1C</a></li>
</ul>
</li>
<li>
<a href="#Item-2">Item 2</a>
<ul class="menu">
<li><a href="#Item-2A">Item 2A</a></li>
<li><a href="#Item-2B">Item 2B</a></li>
</ul>
</li>
<li><a href="#Item-3">Item 3</a></li>
<li><a href="#Item-4">Item 4</a></li>
</ul>`;
afterEach(function () {
plugin.destroy();
document.activeElement.blur();
$html.remove();
});
describe('constructor()', function () {
it('stores the element and plugin options', function () {
$html = $(template).appendTo('body');
plugin = new Foundation.DropdownMenu($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
/*
** Note: for all the following tests testing the currently focused elements,
** IE 9/10/11 may not focus the tested element because is is still rendering.
** To prevent this, we wait after the component initialization.
**
** Fixing this IE behavior in components would require to delay the focus
** for all browsers then trigger a "ready" event.
**
** TODO: Consider this for v6.6
**
** See https://stackoverflow.com/a/2600261/4317384
** See https://stackoverflow.com/a/36032615/4317384
*/
const IErenderWaitTime = 100;
describe('keyboard events', function () {
it('closes current sub menu using ESCAPE', function (done) {
$html = $(template).appendTo('body');
plugin = new Foundation.DropdownMenu($html, {});
setTimeout(() => {
// Open it first
plugin._show($html.find('> li:nth-child(1) > ul'));
$html.find('> li:nth-child(1) > ul > li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ESCAPE'));
$html.find('> li:nth-child(1)').should.not.have.class('is-active');
$html.find('> li:nth-child(1) > ul').should.not.have.class('js-dropdown-active');
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > a')[0]);
done();
}, IErenderWaitTime);
});
describe('horizontal', function() {
beforeEach(function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.DropdownMenu($html, {});
setTimeout(() => done(), IErenderWaitTime);
});
it('moves focus to next tab on ARROW_RIGHT', function () {
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
document.activeElement.should.be.equal($html.find('> li:nth-child(2) > a')[0]);
});
it('moves focus to previous tab on ARROW_LEFT', function () {
$html.find('> li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT'));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > a')[0]);
});
it('opens child element of tab on ARROW_DOWN', function() {
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
$html.find('> li:nth-child(1)').should.have.class('is-active');
$html.find('> li:nth-child(1) > ul').should.have.class('js-dropdown-active');
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(1) > a')[0]);
});
it('moves focus to previous sub element on ARROW_UP', function () {
// Open it first
plugin._show($html.find('> li:nth-child(1) > ul'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(1) > a')[0]);
});
it('opens child element of sub menu on ARROW_RIGHT', function() {
// Open it first
plugin._show($html.find('> li:nth-child(1) > ul'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2)').should.have.class('is-active');
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > ul').should.have.class('js-dropdown-active');
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(2) > ul > li:nth-child(1) > a')[0]);
});
});
describe('vertical', function () {
beforeEach(function(done) {
$html = $(template).addClass('vertical').appendTo('body');
plugin = new Foundation.DropdownMenu($html, {});
setTimeout(() => done(), IErenderWaitTime);
});
it('moves focus to next tab on ARROW_DOWN', function () {
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
document.activeElement.should.be.equal($html.find('> li:nth-child(2) > a')[0]);
});
it('moves focus to previous tab on ARROW_UP', function () {
$html.find('> li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > a')[0]);
});
it('opens child element of tab on ARROW_RIGHT', function() {
$html.find('> li:nth-child(1) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
$html.find('> li:nth-child(1)').should.have.class('is-active');
$html.find('> li:nth-child(1) > ul').should.have.class('js-dropdown-active');
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(1) > a')[0]);
});
it('moves focus to previous sub element on ARROW_UP', function () {
// Open it first
plugin._show($html.find('> li:nth-child(1) > ul'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(1) > a')[0]);
});
it('opens child element of sub menu on ARROW_RIGHT', function() {
// Open it first
plugin._show($html.find('> li:nth-child(1) > ul'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > a').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
$html.find('> li:nth-child(1) > ul > li:nth-child(2)').should.have.class('is-active');
$html.find('> li:nth-child(1) > ul > li:nth-child(2) > ul').should.have.class('js-dropdown-active');
document.activeElement.should.be.equal($html.find('> li:nth-child(1) > ul > li:nth-child(2) > ul > li:nth-child(1) > a')[0]);
});
});
});
});
+20
View File
@@ -0,0 +1,20 @@
describe('Equalizer', function() {
var plugin;
var $html;
// afterEach(function() {
// plugin.destroy();
// $html.remove();
// });
describe('constructor()', function() {
// it('', function() {
// $html = $('').appendTo('body');
// plugin = new Foundation.Equalizer($html, {});
// plugin.$element.should.be.an('object');
// plugin.options.should.be.an('object');
// });
});
});
+214
View File
@@ -0,0 +1,214 @@
describe('Interchange', function () {
var plugin;
var $html;
/**
* Generates paths to different assets
* @param {[type]} type [description]
* @param {[type]} size [description]
* @return {[type]} [description]
*/
var getPath = function(type, size) {
switch (type) {
case 'image':
case 'background':
return `_build/assets/img/interchange/strip_icc()/${size}.jpg`;
default:
return `_build/assets/partials/interchange-${size}.html`;
}
};
/**
* Generates templates to use based on type.
* @param {string} type Type to generate, image, background or template.
* @return {string} Generated template.
*/
var generateTemplate = function(type) {
var type = type || 'template',
tag = type === 'image' ? 'img' : 'div',
path;
switch (type) {
case 'image':
return `<img data-interchange="
[${getPath(type, 'small')}, small],
[${getPath(type, 'medium')}, medium],
[${getPath(type, 'large')}, large]
">`;
case 'background':
return `<div data-interchange="
[${getPath(type, 'small')}, small],
[${getPath(type, 'medium')}, medium],
[${getPath(type, 'large')}, large]
"></div>`;
default:
return `<div data-interchange="
[${getPath(type, 'default')}, small],
[${getPath(type, 'medium')}, medium],
[${getPath(type, 'large')}, large]
"></div>`;
}
};
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(generateTemplate('template')).appendTo('body');
plugin = new Foundation.Interchange($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('replace()', function() {
it('replaces src attribute of img', function() {
$html = $(generateTemplate('image')).attr('data-interchange', '').appendTo('body');
plugin = new Foundation.Interchange($html, {});
plugin.replace(getPath('img', 'large'));
$html.should.have.attr('src', getPath('img', 'large'));
});
it('replaces background style of divs', function() {
$html = $(generateTemplate('background')).attr('data-interchange', '').appendTo('body');
plugin = new Foundation.Interchange($html, {});
plugin.replace(getPath('background', 'large'));
$html[0].style.backgroundImage.should.contain(getPath('background', 'large').replace(/\(/g, '%28').replace(/\)/g, '%29'));
});
it('replaces contents of div with templates', function() {
$html = $(generateTemplate('template')).attr('data-interchange', '').appendTo('body');
plugin = new Foundation.Interchange($html, {});
var spy = sinon.spy($, 'get');
plugin.replace(getPath('template', 'large'));
sinon.assert.calledWith(spy, getPath('template', 'large'));
spy.restore();
});
it('fires replaced.zf.interchange event', function() {
$html = $(generateTemplate('image')).appendTo('body');
plugin = new Foundation.Interchange($html, {});
let spy = sinon.spy();
$html.on('replaced.zf.interchange', spy);
plugin.replace(getPath('image', 'large'));
sinon.assert.called(spy);
});
});
describe('reflow()', function() {
it('calls replace for given media query', function() {
$html = $(generateTemplate('image')).attr('data-interchange', '[image.png, (min-width: 1px)]').appendTo('body');
plugin = new Foundation.Interchange($html, {});
let spy = sinon.spy();
plugin.replace = spy;
plugin._reflow();
sinon.assert.calledWith(spy, 'image.png');
});
});
describe('generateRules()', function() {
it('extracts rules from the plugin element', function() {
$html = $(generateTemplate('image')).appendTo('body');
plugin = new Foundation.Interchange($html, {});
plugin._generateRules($html);
plugin.rules.length.should.be.equal(3);
});
it('extracts special queries from the plugin element', function() {
$html = $(generateTemplate('image')).attr('data-interchange', '[image.png, retina]').appendTo('body');
plugin = new Foundation.Interchange($html, {});
plugin._generateRules($html);
plugin.rules[0].query.should.be.equal(Foundation.Interchange.SPECIAL_QUERIES['retina']);
});
});
describe('addBreakpoints()', function() {
it('adds Foundation breakpoints to special queries', function() {
$html = $(generateTemplate('image')).appendTo('body');
plugin = new Foundation.Interchange($html, {});
var specialQueriesCount = Object.keys(Foundation.Interchange.SPECIAL_QUERIES).length,
foundationMediaQueriesCount = Foundation.MediaQuery.queries.length;
Foundation.MediaQuery.queries.push({
name: 'test-query',
value: 'test-query-value'
})
plugin._addBreakpoints($html);
Object.keys(Foundation.Interchange.SPECIAL_QUERIES).length.should.be.equal(specialQueriesCount + 1);
// Reset Foundation.MediaQueries
Foundation.MediaQuery.queries.length = foundationMediaQueriesCount;
});
});
describe('events()', function () {
it('calls reflow on viewport size change once', function (done) {
$html = $(generateTemplate('image')).appendTo('body');
plugin = new Foundation.Interchange($html, {});
// Debounce: time Triggers is waiting for an other event without firing anything (10 by default)
const debounce = 10;
// Initialize Triggers manually to control and test the debounce time
Foundation.Triggers.Initializers.addMutationEventsListener($(document));
Foundation.Triggers.Initializers.addResizeListener(debounce);
$.triggersInitialized = true;
// Trigger several window resize synchrnously and asynchronously.
// ---
// Timeout delays are most often not respected and the differences between several
// timeouts running in parrallel can be huge. To prevent race conditions we:
// * nest timeout in order to make the delay between them more precise
// * run the test several time to wait for the debounce, which may be finally
// called way after the expected time.
setTimeout(function () {
let spy = sinon.spy(plugin, '_reflow');
$(window).trigger('resize');
$(window).trigger('resize');
setTimeout(function () {
$(window).trigger('resize');
$(window).trigger('resize');
tryInterval({
interval: debounce,
timeout: 1000,
try: () => {
sinon.assert.calledOnce(spy);
},
then: () => {
$.triggersInitialized = false;
done();
},
});
});
});
});
});
});
+93
View File
@@ -0,0 +1,93 @@
describe('Magellan', function() {
var plugin;
var $html, $content;
var generateUl = function(count) {
var html = '';
html += '<ul class="vertical-menu">';
for (var c = 0; c < count; c++) {
html += '<li><a href="#target-' + c + '">Section ' + c + '</a></li>';
}
html += '</ul>';
return html;
};
var generateContent = function(count) {
var html = '';
html += '<div>';
for (var c = 0; c < count; c++) {
html += '<div id="target-' + c + '" style="height: 1000px";>Section ' + c + '</div>';
}
html += '</div>';
return html;
};
afterEach(function() {
plugin.destroy();
$html.remove();
$content.remove();
});
// afterEach(function() {
// plugin.destroy();
// $html.remove();
// });
describe('constructor()', function() {
// it('', function() {
// $html = $('').appendTo('body');
// plugin = new Foundation.Magellan($html, {});
// plugin.$element.should.be.an('object');
// plugin.options.should.be.an('object');
// });
});
describe('scrollToLoc()', function() {
it('scrolls the selected element into viewport', function(done) {
var count = 5, duration = 200;
$html = $(generateUl(count)).appendTo('body');
$content = $(generateContent(count)).appendTo('body');
plugin = new Foundation.Magellan($html, {
animationDuration: duration
});
// Jump to last section
var target = $html.find('a').eq(-1).attr('href');
plugin.scrollToLoc(target);
setTimeout(function() {
var isInViewport = false;
if ($content.find('div').eq(-1).offset().top > $('body').scrollTop() && $content.offset().top < $('body').scrollTop() + $('body').innerHeight()) {
isInViewport = true;
}
isInViewport.should.equal(true);
done();
}, duration);
});
it('fails gracefully when target does not exist', function() {
var count = 5, duration = 200;
$html = $(generateUl(count)).appendTo('body');
$content = $(generateContent(count - 1)).appendTo('body');
plugin = new Foundation.Magellan($html, {
animationDuration: duration
});
var hasError = false;
var targets = $html.find('a');
try {
var target = $(targets).eq(-1).attr('href');
plugin.scrollToLoc(target);
}
catch (err) {
hasError = true;
}
hasError.should.equal(false);
});
});
});
+275
View File
@@ -0,0 +1,275 @@
describe('Off Canvas', function() {
var plugin;
var $html;
var template = `<div class="off-canvas-wrapper">
<div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
<div class="off-canvas position-left" id="offCanvas" data-off-canvas data-content-scroll="false">
<!-- Close button -->
<button class="close-button" aria-label="Close menu" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<!-- Menu -->
<ul class="vertical menu">
<li><a href="#">Foundation</a></li>
<li><a href="#">Dot</a></li>
<li><a href="#">ZURB</a></li>
<li><a href="#">Com</a></li>
<li><a href="#">Slash</a></li>
<li><a href="#">Sites</a></li>
</ul>
</div>
<div class="off-canvas-content" data-off-canvas-content>
<!-- Page content -->
PAGE_CONTENT.
<!-- Triggers -->
<button type="button" class="button" data-toggle="offCanvas">Open Menu</button>
</div>
</div>
</div>`;
afterEach(function() {
plugin.destroy();
document.activeElement.blur();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('finds triggers for the Off Canvas', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
plugin.$triggers.length.should.be.equal(1);
});
it('sets ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
plugin.$element.should.have.attr('aria-hidden', 'true');
plugin.$triggers.should.have.attr('aria-controls', plugin.$element.attr('id'));
plugin.$triggers.should.have.attr('aria-expanded', 'false');
});
it('closes Off Canvas on outside click if closeOnClick option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {closeOnClick: true});
plugin.$overlay.should.be.an('object');
$html.one('opened.zf.offcanvas', function() {
plugin.$overlay.trigger('click');
plugin.$element.should.not.have.class('is-open');
done();
});
plugin.open();
});
});
describe('open()', function() {
it('toggles ARIA attributes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
//$html.one(Foundation.transitionend($html), function() {
$html.one('opened.zf.offcanvas', function() {
plugin.$triggers.should.have.attr('aria-expanded', 'true');
plugin.$element.should.have.attr('aria-hidden', 'false');
done();
});
plugin.open();
});
it('adds active classes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
setTimeout(function() {
plugin.$element.should.have.class('is-open');
$('body').should.have.class('is-off-canvas-open');
done();
}, 1);
});
plugin.open();
});
it('focusses Off Canvas if autoFocus option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {autoFocus: true});
plugin.$element.one(Foundation.transitionend(plugin.$element),function() {
setTimeout(function() {
plugin.$element.find('a, button')[0].should.be.equal(document.activeElement);
done();
}, 1);
});
plugin.open();
// fake transitionend for console tests
plugin.$element.triggerHandler(Foundation.transitionend(plugin.$element));
});
it('traps focus if trapFocus option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {trapFocus: true});
let spy = sinon.spy(Foundation.Keyboard, 'trapFocus');
$html.one(Foundation.transitionend($html), function() {
sinon.assert.called(spy);
Foundation.Keyboard.trapFocus.restore();
done();
});
plugin.open();
});
it('fires opened.zf.offcanvas event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
done();
});
plugin.open();
});
});
describe('close()', function() {
it('toggles ARIA attributes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
plugin.close();
plugin.$triggers.should.have.attr('aria-expanded', 'false');
plugin.$element.should.have.attr('aria-hidden', 'true');
done();
});
// Open it first
plugin.open();
});
it('removes active classes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
setTimeout(function() {
plugin.close();
plugin.$element.should.not.have.class('is-open');
$('body').should.not.have.class('is-off-canvas-open');
done();
}, 1);
});
// Open it first
plugin.open();
});
it('fires closed.zf.offcanvas event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
$html.one('closed.zf.offcanvas', function() {
done();
});
plugin.close();
});
// Open it first
plugin.open();
});
it('releases focus if trapFocus option is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {trapFocus: true});
$html.one(Foundation.transitionend($html), function() {
let spy = sinon.spy(Foundation.Keyboard, 'releaseFocus');
plugin.close();
sinon.assert.called(spy);
Foundation.Keyboard.releaseFocus.restore();
});
// Open it first...
plugin.open();
});
});
describe('toggle()', function() {
it('opens a closed Off Canvas', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
plugin.$element.should.have.class('is-open');
done();
});
plugin.toggle();
});
it('closes an open Off Canvas', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
plugin.toggle();
plugin.$element.should.not.have.class('is-open');
done();
});
// Open it first
plugin.toggle();
});
});
describe('keyboard events', function() {
it('closes Off Canvas on ESCAPE', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.OffCanvas($html.find('[data-off-canvas]'), {});
$html.one('opened.zf.offcanvas', function() {
plugin.$element.focus()
.trigger(window.mockKeyboardEvent('ESCAPE'));
plugin.$element.should.not.have.class('is-open');
done();
});
// Open it first
plugin.open();
});
});
});
+220
View File
@@ -0,0 +1,220 @@
describe('Orbit', function() {
var plugin;
var $html;
var template = `<div class="orbit" role="region" aria-label="Favorite Space Pictures" data-orbit>
<ul class="orbit-container">
<button class="orbit-previous"><span class="show-for-sr">Previous Slide</span>&#9664;&#xFE0E;</button>
<button class="orbit-next"><span class="show-for-sr">Next Slide</span>&#9654;&#xFE0E;</button>
<li class="is-active orbit-slide">
Slide #1 content.
</li>
<li class="orbit-slide">
Slide #2 content.
</li>
<li class="orbit-slide">
Slide #3 content.
</li>
<li class="orbit-slide">
Slide #4 content.
</li>
</ul>
<nav class="orbit-bullets">
<button class="is-active" data-slide="0"><span class="show-for-sr">First slide details.</span><span class="show-for-sr">Current Slide</span></button>
<button data-slide="1"><span class="show-for-sr">Second slide details.</span></button>
<button data-slide="2"><span class="show-for-sr">Third slide details.</span></button>
<button data-slide="3"><span class="show-for-sr">Fourth slide details.</span></button>
</nav>
</div>`;
Foundation.Orbit.defaults.useMUI = false;
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.$element.should.be.an('object');
plugin.$wrapper.should.be.an('object');
plugin.$slides.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('shows the first slide', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-slide').eq(0).should.be.visible;
});
it('hides all slides except the first one', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-slide').each(function(index) {
if (index === 0) {return;} // Not for the first one as this is visible
$(this).should.be.hidden;
});
});
it('makes slide with is-active class active initially', function() {
$html = $(template).appendTo('body');
$html.find('.orbit-slide.is-active').removeClass('is-active');
$html.find('.orbit-slide').eq(2).addClass('is-active');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-slide').eq(2).should.be.visible;
});
});
describe('loadBullets()', function() {
it('stores the bullets', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.$bullets.should.be.an('object');
});
});
describe('changeSlide()', function() {
it('changes slides to the next one for ltr is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.changeSlide(true);
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(1).should.be.visible;
});
it('changes slides to the last one for ltr is false', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.changeSlide(false);
$html.find('.orbit-slide').eq(0).should.not.have.class('is-active');
$html.find('.orbit-slide').eq(-1).should.have.class('is-active');
});
it('changes slides to the chosen one', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.changeSlide(true, $html.find('.orbit-slide').eq(2), 2);
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(2).should.be.visible;
});
it('toggles ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.changeSlide(true);
$html.find('.orbit-slide').eq(0).should.not.have.attr('aria-live');
$html.find('.orbit-slide').eq(1).should.have.attr('aria-live', 'polite');
});
it('fires beforeslidechange.zf.orbit event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.on('beforeslidechange.zf.orbit', function() {
// Old slide should still be active
$html.find('.orbit-slide').eq(0).should.be.visible;
done();
});
plugin.changeSlide(true);
});
it('fires slidechange.zf.orbit event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.on('slidechange.zf.orbit', function() {
// New slide is already active
$html.find('.orbit-slide').eq(1).should.be.visible;
done();
});
plugin.changeSlide(true);
});
});
describe('updateBullets()', function() {
it('updates the bullets', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
plugin.changeSlide(true);
$html.find('.orbit-bullets [data-slide]').eq(0).should.not.have.class('is-active');
$html.find('.orbit-bullets [data-slide]').eq(1).should.have.class('is-active');
});
});
describe('events()', function() {
it('changes slides on bullet click', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-bullets [data-slide]').eq(2).trigger('click');
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(2).should.be.visible;
});
it('changes slides to the previous one', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-previous').trigger('click');
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(-1).should.be.visible;
});
it('changes slides to the next one', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
$html.find('.orbit-next').trigger('click');
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(1).should.be.visible;
});
});
describe('geoSync()', function() {
it('changes slides automatically based on timerDelay option', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {timerDelay: 200});
setTimeout(function() {
$html.find('.orbit-slide').eq(0).should.be.hidden;
$html.find('.orbit-slide').eq(1).should.be.visible;
done();
}, 201);
});
});
describe('keyboard events', function() {
it('moves switches to next slide using ARROW_RIGHT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
let spy = sinon.spy(plugin, 'changeSlide');
plugin.$wrapper.focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
sinon.assert.calledWith(spy, true);
});
it('moves switches to previous slide using ARROW_LEFT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Orbit($html, {});
let spy = sinon.spy(plugin, 'changeSlide');
plugin.$wrapper.focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT'));
sinon.assert.calledWith(spy, false);
});
});
});
@@ -0,0 +1,20 @@
describe('Responsive Menu', function() {
var plugin;
var $html;
// afterEach(function() {
// plugin.destroy();
// $html.remove();
// });
describe('constructor()', function() {
// it('', function() {
// $html = $('').appendTo('body');
// plugin = new Foundation.ResponsiveMenu($html, {});
// plugin.$element.should.be.an('object');
// plugin.options.should.be.an('object');
// });
});
});
@@ -0,0 +1,20 @@
describe('Responsive Toggle', function() {
var plugin;
var $html;
// afterEach(function() {
// plugin.destroy();
// $html.remove();
// });
describe('constructor()', function() {
// it('', function() {
// $html = $('').appendTo('body');
// plugin = new Foundation.ResponsiveToggle($html, {});
// plugin.$element.should.be.an('object');
// plugin.options.should.be.an('object');
// });
});
});
+414
View File
@@ -0,0 +1,414 @@
describe('Reveal', function() {
var plugin;
var $html;
var template = `<div class="reveal" id="exampleModal1" data-reveal>
Modal content
<button class="close-button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>`;
afterEach(function() {
plugin.destroy();
document.activeElement.blur();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('sets ARIA attributes for modal', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.should.have.attr('aria-hidden', 'true');
$html.should.have.attr('role', 'dialog');
});
it('detects anchor if one exists', function() {
$html = $(template).appendTo('body');
var $anchor = $('<button data-open="exampleModal1">Open</button>').appendTo('body');
plugin = new Foundation.Reveal($html, {});
plugin.$anchor[0].should.be.equal($anchor[0]);
$anchor.remove();
});
it('sets ARIA attributes for anchor if one exists', function() {
$html = $(template).appendTo('body');
var $anchor = $('<button data-open="exampleModal1">Open</button>').appendTo('body');
plugin = new Foundation.Reveal($html, {});
$anchor.should.have.attr('aria-haspopup', 'true');
$anchor.should.have.attr('aria-controls', $html.attr('id'));
$anchor.remove();
});
});
describe('makeOverlay()', function() {
it('creates an overlay if overlay option is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true});
plugin.$overlay.should.be.an('object');
plugin.$overlay.should.have.class('reveal-overlay');
$.contains(document.body, plugin.$overlay[0]).should.be.true;
});
});
describe('open()', function() {
it('opens the modal', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.on('open.zf.reveal', function() {
$html.should.be.visible;
done();
});
plugin.open();
});
it('opens the overlay', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true});
$html.on('open.zf.reveal', function() {
plugin.$overlay.should.be.visible;
done();
});
plugin.open();
});
it('toggles ARIA attributes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.on('open.zf.reveal', function() {
$html.should.have.attr('aria-hidden', 'false');
$html.should.have.attr('tabindex', '-1');
done();
});
plugin.open();
});
it('adds class to body', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.on('open.zf.reveal', function() {
$('html').should.have.class('is-reveal-open');
done();
});
plugin.open();
});
it('adds optional overlay classes overlay element', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {additionalOverlayClasses: 'default'});
$html.on('open.zf.reveal', function() {
$('.reveal-overlay').should.have.class('default');
done();
});
plugin.open();
});
// TODO: Check if this.$element.trigger('closeme.zf.reveal', this.id) is correctly used.
// it('closes previously opened modal if multipleOpened option is false', function(done) {
// $html = $(template).appendTo('body');
// $html2 = $(template).attr('id', 'exampleModal2').appendTo('body');
// plugin = new Foundation.Reveal($html, {multipleOpened: false});
// plugin2 = new Foundation.Reveal($html2, {multipleOpened: false});
// plugin.open();
// plugin2.open();
// $html.should.be.hidden;
// plugin2.destroy();
// $html2.remove();
// });
it('fires open.zf.reveal event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.on('open.zf.reveal', function() {
$html.should.be.visible;
done();
});
plugin.open();
});
it('traps focus if trapFocus option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {trapFocus: true});
let spy = sinon.spy(Foundation.Keyboard, 'trapFocus');
$html.on('open.zf.reveal', function() {
sinon.assert.called(spy);
Foundation.Keyboard.trapFocus.restore();
done();
});
plugin.open();
});
});
describe('close()', function() {
it('closes the modal', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.be.hidden;
done();
});
plugin.close();
});
it('closes the overlay', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
plugin.$overlay.should.be.hidden;
done();
});
plugin.close();
});
it('toggles ARIA attributes', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.have.attr('aria-hidden', 'true');
done();
});
plugin.close();
});
it('removes class from body', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$('html').should.not.have.class('is-reveal-open');
done();
});
plugin.close();
});
it('does not remove class from body if another reveal is open', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {multipleOpened: true});
let $html2 = $(template).attr('id', 'exampleModal2').appendTo('body');
let plugin2 = new Foundation.Reveal($html2, {multipleOpened: true, vOffset: 10});
// Open both first
plugin.open();
plugin2.open();
$html.on('closed.zf.reveal', function() {
$('html').should.have.class('is-reveal-open');
plugin2.destroy();
$html2.remove();
done();
});
plugin.close();
});
it('fires closed.zf.reveal event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.be.hidden;
done();
});
plugin.close();
});
it('releases focus if trapFocus option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {trapFocus: true});
// Open it first
plugin.open();
let spy = sinon.spy(Foundation.Keyboard, 'releaseFocus');
$html.on('closed.zf.reveal', function() {
sinon.assert.called(spy);
Foundation.Keyboard.releaseFocus.restore();
done();
});
plugin.close();
});
it('sets focus to anchor', function(done) {
$html = $(template).appendTo('body');
var $anchor = $('<button data-open="exampleModal1">Open</button>').appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
setTimeout(function() {
$anchor[0].should.be.equal(document.activeElement);
$anchor.remove();
done();
}, 0);
});
plugin.close();
});
it('sets focus to anchor that opened it', function(done) {
$html = $(template).appendTo('body');
var $anchor = $('<button data-open="exampleModal1">Open</button>').appendTo('body');
var $anchor2 = $('<button data-open="exampleModal1">Open2</button>').appendTo('body');
plugin = new Foundation.Reveal($html, {});
$anchor.focus();
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
setTimeout(function() {
$anchor[0].should.be.equal(document.activeElement);
$anchor.remove();
$anchor2.remove();
done();
}, 0);
});
plugin.close();
});
});
describe('toggle()', function() {
it('opens a closed modal', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true});
$html.on('open.zf.reveal', function() {
plugin.$overlay.should.be.visible;
done();
});
plugin.open();
});
it('closes an open modal', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.be.hidden;
done();
});
plugin.close();
});
});
describe('events()', function() {
it('opens the modal on anchor click', function(done) {
$html = $(template).appendTo('body');
var $anchor = $('<button data-open="exampleModal1">Open</button>').appendTo('body');
plugin = new Foundation.Reveal($html, {});
$html.on('open.zf.reveal', function() {
plugin.$overlay.should.be.visible;
$anchor.remove();
done();
});
$anchor.trigger('click');
});
it('closes a modal on overlay click if closeOnClick option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true, closeOnClick: true});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.be.hidden;
done();
});
plugin.$overlay.trigger('click');
});
it('not closes a modal on overlay click if closeOnClick option is true', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {overlay: true, closeOnClick: false});
// Open it first
plugin.open();
plugin.$overlay.trigger('click');
// Add timeout to make sure it does not close
// Timeout is required because closed event will not be fired
setTimeout(function() {
$html.should.be.visible;
done();
}, 10);
});
it('closes Reveal with click on close button', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Reveal($html, {});
// Open it first
plugin.open();
$html.on('closed.zf.reveal', function() {
$html.should.be.hidden;
done();
});
$html.find('[data-close]').focus()
.trigger('click');
});
});
});
+263
View File
@@ -0,0 +1,263 @@
describe('Slider', function() {
var plugin;
var $html;
var template = `<div class="slider" data-slider>
<span class="slider-handle" data-slider-handle role="slider" tabindex="1"></span>
<span class="slider-fill" data-slider-fill></span>
<input type="hidden">
</div>`;
Foundation.Slider.defaults.moveTime = 0;
Foundation.Slider.defaults.changedDelay = 0;
afterEach(function(done) {
// Timeout needed because even with changeDelay = 0 the changed.zf.slider event may be fired after this hook
plugin.destroy();
$html.remove();
done();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('stores handle, inout and fill elements', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin.$handle.should.be.an('object');
plugin.$input.should.be.an('object');
plugin.$fill.should.be.an('object');
});
it('stores two handle and input elements for two sided slider', function() {
$html = $(template).append('<span class="slider-handle" data-slider-handle role="slider" tabindex="1"></span><input type="hidden">')
.appendTo('body');
plugin = new Foundation.Slider($html, {doubleSided: true});
plugin.$handle2.should.be.an('object');
plugin.$input2.should.be.an('object');
});
it('is disabled when disable option is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {disabled: true});
$html.should.have.class('disabled');
});
});
describe('setHandlePos()', function() {
it('positions the handle', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin._setHandlePos(plugin.$handle, 10, true);
plugin.$handle[0].style.left.should.not.be.equal('');
});
it('does nothing if disabled option is true', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {disabled: true});
plugin._setHandlePos(plugin.$handle, 10, true);
plugin.$handle[0].style.left.should.be.equal('');
});
it('fires changed.zf.slider event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {changedDelay: 50});
$html.on('changed.zf.slider', function(e, $handle) {
$handle[0].should.be.equal(plugin.$handle[0]);
done();
});
// Rapidly change to see if event fires only once
for (let i = 0; i < 5; i++) {
setTimeout(function() {
plugin._setHandlePos(plugin.$handle, i * 10, true);
}, i * 20);
}
});
it('fires moved.zf.slider event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
let timesCallbackCalled = 0;
$html.on('moved.zf.slider', function(e, $handle) {
if (++timesCallbackCalled === 5) {
$handle[0].should.be.equal(plugin.$handle[0]);
done();
}
});
// Rapidly change to see if event fires multiple times
for (let i = 0; i < 5; i++) {
setTimeout(function() {
plugin._setHandlePos(plugin.$handle, i * 10, true);
}, i * 20);
}
});
});
describe('setValues()', function() {
it('updates ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin._setValues(plugin.$handle, 10);
plugin.$handle.should.have.attr('aria-valuenow', '10');
});
it('updates input value', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin._setValues(plugin.$handle, 10);
plugin.$input.val().should.have.be.equal('10');
});
});
describe('setInitAttr()', function() {
it('adds ARIA attributes to handle', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 50,
end: 70,
start: 20,
vertical: true
});
plugin.$handle.should.have.attr('role', 'slider');
plugin.$handle.should.have.attr('aria-controls', plugin.$handle.attr('id'));
plugin.$handle.should.have.attr('aria-valuemax', '70');
plugin.$handle.should.have.attr('aria-valuemin', '20');
plugin.$handle.should.have.attr('aria-valuenow', '50');
plugin.$handle.should.have.attr('aria-orientation', 'vertical');
plugin.$handle.should.have.attr('tabindex', '0');
});
it('adds attributes to input', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin.$input.should.have.attr('max', '100');
plugin.$input.should.have.attr('min', '0');
plugin.$input.should.have.attr('step', '1');
});
});
describe('adjustValue()', function() {
it('handles positive values', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin._adjustValue(null, 1).should.equal(1);
plugin._adjustValue(null, 2).should.equal(2);
plugin._adjustValue(null, 1.2).should.equal(1);
plugin._adjustValue(null, 1.9).should.equal(2);
plugin._adjustValue(null, 1.5).should.equal(2);
});
it('handles negative values', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin._adjustValue(null, -1).should.equal(-1);
plugin._adjustValue(null, -2).should.equal(-2);
plugin._adjustValue(null, -1.2).should.equal(-1);
plugin._adjustValue(null, -1.9).should.equal(-2);
plugin._adjustValue(null, -1.5).should.equal(-1);
});
});
describe('keyboard events', function() {
it('sets value to minimum using HOME', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('HOME'));
plugin.$handle.should.have.attr('aria-valuenow', plugin.$handle.attr('aria-valuemin'));
});
it('increases value by step size on ARROW_RIGHT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
plugin.$handle.should.have.attr('aria-valuenow', (10 + 1).toString());
});
it('increases value by step size on ARROW_UP', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
plugin.$handle.should.have.attr('aria-valuenow', (10 + 1).toString());
});
it('decreases value by step size on ARROW_LEFT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT'));
plugin.$handle.should.have.attr('aria-valuenow', (10 - 1).toString());
});
it('decreases value by step size on ARROW_DOWN', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
plugin.$handle.should.have.attr('aria-valuenow', (10 - 1).toString());
});
it('decreases value by step size times 10 on SHIFT_ARROW_RIGHT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT', {shift: true}));
plugin.$handle.should.have.attr('aria-valuenow', (10 + 1 * 10).toString());
});
it('decreases value by step size times 10 on SHIFT_ARROW_LEFT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Slider($html, {
initialStart: 10,
step: 1
});
plugin.$handle.focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT', {shift: true}));
plugin.$handle.should.have.attr('aria-valuenow', (10 - 1 * 10).toString());
});
});
});
+20
View File
@@ -0,0 +1,20 @@
describe('Sticky', function() {
var plugin;
var $html;
// afterEach(function() {
// plugin.destroy();
// $html.remove();
// });
describe('constructor()', function() {
// it('', function() {
// $html = $('').appendTo('body');
// plugin = new Foundation.Sticky($html, {});
// plugin.$element.should.be.an('object');
// plugin.options.should.be.an('object');
// });
});
});
+183
View File
@@ -0,0 +1,183 @@
describe('Tabs', function() {
var plugin;
var $html;
var template = `
<div>
<ul class="tabs" data-tabs id="example-tabs">
<li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Tab 1</a></li>
<li class="tabs-title"><a href="#panel2">Tab 2</a></li>
<li class="tabs-title"><a data-tabs-target="panel3" href="#/panel3">Tab 3</a></li>
</ul>
<div class="tabs-content" data-tabs-content="example-tabs">
<div class="tabs-panel is-active" id="panel1">
<p>one</p>
<p>Check me out! I'm a super cool Tab panel with text content!</p>
</div>
<div class="tabs-panel" id="panel2">
<p>two</p>
<p>Check me out! I'm a super cool Tab panel with text content!</p>
</div>
<div class="tabs-panel" id="panel3">
<p>three</p>
<p>Check me out! I'm a super cool Tab panel with text content!</p>
</div>
</div>
</div>`;
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('sets ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
// Panels
$html.find('#panel1').should.have.attr('role', 'tabpanel');
$html.find('#panel1').should.have.attr('aria-labelledby', $html.find('[href="#panel1"]').attr('id'));
$html.find('#panel1').should.not.have.attr('aria-hidden');
$html.find('#panel2').should.have.attr('aria-hidden', 'true');
// Links
$html.find('[href="#panel1"]').should.have.attr('role', 'tab');
$html.find('[href="#panel1"]').should.have.attr('aria-controls', $html.find('panel1').attr('id'));
$html.find('[href="#panel1"]').should.have.attr('aria-selected', 'true');
$html.find('[href="#panel2"]').should.have.attr('aria-selected', 'false');
// Tab list items
$html.find('[href="#panel1"]').parent().should.have.attr('role', 'presentation');
});
});
describe('selectTab()', function() {
it('opens the selected tab via jQuery element', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab($html.find('#panel2'));
$html.find('#panel2').should.be.visible;
});
it('opens the selected tab via id string', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#panel2');
$html.find('#panel2').should.be.visible;
});
it('opens the selected tab with data-tabs-target attribute', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#/panel3');
$html.find('#panel3').should.be.visible;
});
});
describe('_handleTabChange()', function() {
it('opens the selected tab', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#panel2');
$html.find('#panel2').should.be.visible;
$html.find('#panel2').should.have.class('is-active');
});
it('sets ARIA attributes for open tab', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#panel2');
$html.find('#panel2').should.have.not.attr('aria-hidden');
$html.find('[href="#panel2"]').should.have.attr('aria-selected', 'true');
});
it('hides the open tab', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#panel2');
$html.find('#panel1').should.be.hidden;
$html.find('#panel1').should.not.have.class('is-active');
});
it('sets ARIA attributes for closed tab', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
plugin.selectTab('#panel2');
$html.find('#panel1').should.be.have.attr('aria-hidden', 'true');
$html.find('[href="#panel1"]').should.be.have.attr('aria-selected', 'false');
});
it('fires change.zf.tabs event with target as data', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
$html.one('change.zf.tabs', function(e, $target) {
e.stopPropagation();
$html.find('[href="#panel2"]').parent()[0].should.be.equal($target[0]);
done();
});
plugin.selectTab('#panel2');
});
});
describe('keyboard events', function() {
it('switches to next tab on ARROW_RIGHT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
$html.find('[href="#panel1"]').focus()
.trigger(window.mockKeyboardEvent('ARROW_RIGHT'));
$html.find('#panel2').should.be.visible;
$html.find('#panel2').should.have.class('is-active');
});
it('switches to next tab on ARROW_DOWN', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
$html.find('[href="#panel1"]').focus()
.trigger(window.mockKeyboardEvent('ARROW_DOWN'));
$html.find('#panel2').should.be.visible;
$html.find('#panel2').should.have.class('is-active');
});
it('switches to previous tab on ARROW_LEFT', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
$html.find('[href="#panel2"]').focus()
.trigger(window.mockKeyboardEvent('ARROW_LEFT'));
$html.find('#panel1').should.be.visible;
$html.find('#panel1').should.have.class('is-active');
});
it('switches to previous tab on ARROW_UP', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tabs($html.find('[data-tabs]'), {});
$html.find('[href="#panel2"]').focus()
.trigger(window.mockKeyboardEvent('ARROW_UP'));
$html.find('#panel1').should.be.visible;
$html.find('#panel1').should.have.class('is-active');
});
});
});
+143
View File
@@ -0,0 +1,143 @@
describe('Toggler', function() {
var plugin;
var $html;
afterEach(function() {
plugin.destroy();
$html.remove();
});
function appendTriggers() {
return $(`<div>
<a data-open="toggler">Open</a>
<a data-close="toggler">Close</a>
<a data-toggle="toggler">Toggle</a>
</div>`).appendTo('body')
}
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('stores the class defined on the data-toggler attribute', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
plugin.className.should.equal('class');
});
it('stores the class defined on the data-toggler attribute (with leading dot)', function() {
$html = $('<div id="toggler" data-toggler=".class"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
plugin.className.should.equal('class');
});
it('stores defined animation classes', function() {
$html = $('<div id="toggler" data-toggler data-animate="fade-in fade-out"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
plugin.animationIn.should.equal('fade-in');
plugin.animationOut.should.equal('fade-out');
});
it('adds Aria attributes to click triggers', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
var $triggers = appendTriggers();
plugin = new Foundation.Toggler($html, {});
$triggers.find('[data-open], [data-close], [data-toggle]').should.have.attr('aria-controls', 'toggler');
$triggers.remove();
});
it('sets aria-expanded to true if the element is visible', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
var $triggers = appendTriggers();
plugin = new Foundation.Toggler($html, {});
$triggers.find('[data-open], [data-close], [data-toggle]').should.have.attr('aria-expanded', 'true');
$triggers.remove();
});
it('sets aria-expanded to false if the element is invisible', function() {
var $css = $('<style>#toggler { display: none }</style>').appendTo('body');
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
var $triggers = appendTriggers();
plugin = new Foundation.Toggler($html, {});
$triggers.find('[data-open], [data-close], [data-toggle]').should.have.attr('aria-expanded', 'false');
$triggers.remove();
$css.remove();
});
});
describe('toggle()', function() {
it('calls Toggler._toggleClass() if the element toggles with a class');
it('calls Toggler._toggleAnimate() if the element toggles with animation');
});
describe('toggleClass()', function() {
it('toggles a class on the element', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
plugin._toggleClass();
$('#toggler').should.have.class('class');
plugin._toggleClass();
$('#toggler').should.not.have.class('class');
});
it('updates aria-expanded after the class is toggled', function() {
$html = $('<div id="toggler" data-toggler="class"></div>').appendTo('body');
var $triggers = appendTriggers();
plugin = new Foundation.Toggler($html, {});
plugin._toggleClass();
$triggers.find('[data-open], [data-close], [data-toggle]').should.have.attr('aria-expanded', 'true');
plugin._toggleClass();
$triggers.find('[data-open], [data-close], [data-toggle]').should.have.attr('aria-expanded', 'false');
$triggers.remove();
});
});
// [TODO] Re-enable this if you can get it working in PhantomJS
xdescribe('toggleAnimate()', function() {
it('animates an invisible element in', function(done) {
var $css = $('<style>#toggler { display: none; }</style>').appendTo('body');
$html = $('<div id="toggler" data-toggler data-animate="fade-in fade-out"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
$html.on('on.zf.toggler', function() {
$('#toggler').should.be.visible;
$css.remove();
done();
});
plugin._toggleAnimate();
});
it('animates a visible element out', function(done) {
$html = $('<div id="toggler" data-toggler data-animate="fade-in fade-out"></div>').appendTo('body');
plugin = new Foundation.Toggler($html, {});
$html.on('off.zf.toggler', function() {
$('#toggler').should.be.hidden;
done();
});
plugin._toggleAnimate();
});
});
});
+153
View File
@@ -0,0 +1,153 @@
describe('Tooltip', function() {
var plugin;
var $html;
var template = `
<span data-tooltip aria-haspopup="true" class="has-tip" tabindex="1" title="TOOLTIP_CONTENT">
TEXT
</span>`;
Foundation.Tooltip.defaults.showOn = 'all';
Foundation.Tooltip.defaults.fadeOutDuration = 0;
Foundation.Tooltip.defaults.fadeInDuration = 0;
afterEach(function() {
plugin.destroy();
$html.remove();
});
describe('constructor()', function() {
it('stores the element and plugin options', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
plugin.$element.should.be.an('object');
plugin.options.should.be.an('object');
});
});
describe('init()', function() {
it('has value of title attribute as content', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
plugin.template.text().should.equal('TOOLTIP_CONTENT');
});
it('has value of tipText option as content', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {tipText: 'TOOLTIP_CONTENT_OPTION'});
plugin.template.text().should.equal('TOOLTIP_CONTENT_OPTION');
});
it('uses value of template option as template', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {template: '<div class="TEMPLATE_OPTION"></div>'});
plugin.template.should.have.class('TEMPLATE_OPTION');
});
it('uses value of triggerClass option as trigger class', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {triggerClass: 'TRIGGER_CLASS_OPTION'});
plugin.$element.should.have.class('TRIGGER_CLASS_OPTION');
});
it('sets ARIA attributes', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
plugin.$element.should.have.attr('aria-describedby', plugin.template.attr('id'));
plugin.template.should.have.attr('aria-hidden', 'true');
plugin.template.should.have.attr('role', 'tooltip');
});
});
describe('buildTemplate()', function() {
it('uses value of templateClasses option as template class', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {templateClasses: 'TOOLTIP_CLASS_OPTION'});
plugin.template.should.have.class('TOOLTIP_CLASS_OPTION');
});
});
describe('show()', function() {
it('shows the tooltip', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
plugin.show();
plugin.template.should.be.visible;
plugin.template.should.have.attr('aria-hidden', 'false');
});
it('fires show.zf.tooltip event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
$html.on('show.zf.tooltip', function() {
plugin.template.should.be.visible;
done();
});
plugin.show();
});
});
describe('hide()', function() {
it('hides the tooltip', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
// Show first
plugin.show();
plugin.hide();
plugin.template.should.be.hidden;
plugin.template.should.have.attr('aria-hidden', 'true');
});
it('fires hide.zf.tooltip event', function(done) {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
// Open it first
plugin.show();
$html.on('hide.zf.tooltip', function() {
plugin.template.should.be.hidden;
done();
});
plugin.hide();
});
});
describe('toggle()', function() {
it('shows a hidden tooltip', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
plugin.toggle();
plugin.template.should.be.visible;
plugin.template.should.have.attr('aria-hidden', 'false');
});
it('hides a visible tooltip', function() {
$html = $(template).appendTo('body');
plugin = new Foundation.Tooltip($html, {});
// Show first
plugin.show();
plugin.toggle();
plugin.template.should.be.hidden;
plugin.template.should.have.attr('aria-hidden', 'true');
});
});
});
+82
View File
@@ -0,0 +1,82 @@
describe('Foundation core', function() {
it('exists on the window', function() {
(window.Foundation).should.be.an('object');
});
it('is a jQuery prototype function', function() {
($.fn.foundation).should.to.be.a('function');
});
describe('plugin()', function() {
afterEach(function() {
delete Foundation._plugins['plugin'];
delete Foundation.Plugin;
});
it('adds Foundation plugins', function() {
function Plugin() {}
Foundation.plugin(Plugin, 'Plugin');
(Foundation._plugins['plugin']).should.be.a('function');
(Foundation.Plugin).should.be.a('function');
});
it('uses the name of the Plugin class/function if one is not provided', function() {
function Plugin() {}
Foundation.plugin(Plugin);
(Foundation._plugins['plugin']).should.be.a('function');
(Foundation.Plugin).should.be.a('function');
});
});
describe('registerPlugin()', function() {
it('registers a new instance of a plugin');
});
describe('unregisterPlugin()', function() {
it('un-registers a plugin being destroyed');
});
describe('reInit()', function() {
});
describe('reflow()', function() {
});
describe('getFnName()', function() {
it('should handle a function declaration', function() {
function A() {};
var name = Foundation.getFnName(A);
name.should.be.a('string');
name.should.be.equal('A');
});
it('should handle an anonymous function expression', function() {
var name = Foundation.getFnName(function(){});
// Inferred names (i.e. `var name = function() {}`) are not tested as they are widely supported
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Inferred_function_names
name.should.be.a('string');
name.should.be.equal('');
});
it('should handle a named function expression', function() {
var D = function foo(){};
var name = Foundation.getFnName(D);
name.should.be.a('string');
name.should.be.equal('foo');
});
});
describe('transitionEnd()', function() {
});
describe('onLoad()', function (done) {
});
describe('throttle()', function() {
});
});
+41
View File
@@ -0,0 +1,41 @@
describe('Foundation core utils', function() {
describe('rtl()', function() {
it('detects the text direction on the document', function() {
(Foundation.rtl()).should.be.false;
$('html').attr('dir', 'rtl');
(Foundation.rtl()).should.be.true;
$('html').attr('dir', 'ltr');
});
});
describe('GetYoDigits()', function() {
it('generates a random ID matching a given length', function() {
var id = Foundation.GetYoDigits(6);
id.should.be.a('string');
id.should.have.lengthOf(6);
});
it('can append a namespace to the number', function() {
var id = Foundation.GetYoDigits(6, 'plugin');
id.should.be.a('string');
id.should.have.lengthOf(6 + '-plugin'.length);
id.should.contain('-plugin');
});
});
describe('RegExpEscape()', function() {
it('escape all special characters in a string for RegExp', function () {
const str = 'abc012-[]{}()*+?.,\\^$|#\s\t\r\n';
const notstr = 'abc012-[]{}not-the-escaped-string';
const reg = new RegExp(Foundation.RegExpEscape(str), 'g');
reg.test(str).should.be.true;
reg.test(notstr).should.be.false;
});
});
});
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../../_build/assets/js/foundation.js"></script>
<script src="../../node_modules/mocha/mocha.js"></script>
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
<link rel="stylesheet" href="../../_build/assets/css/foundation-float.css">
<link rel="stylesheet" href="../../node_modules/motion-ui/dist/motion-ui.css">
</head>
<body>
<div id="mocha"></div>
<script src="../../node_modules/chai/chai.js"></script>
<script src="../../node_modules/chai-jquery/chai-jquery.js"></script>
<script src="../../node_modules/sinon/pkg/sinon-no-sourcemaps.js"></script>
<script>
mocha.setup({
ui: 'bdd',
timeout: 5000,
});
chai.should();
</script>
<script src="lib/keyboard-event-mock.js"></script>
<script src="lib/utils.js"></script>
<script src="js-tests.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
(function(global) {
var keyCodes = {
'A': 65,
'TAB': 9,
'ENTER': 13,
'ESCAPE': 27,
'SPACE': 32,
'END': 35,
'HOME': 36,
'ARROW_LEFT': 37,
'ARROW_UP': 38,
'ARROW_RIGHT': 39,
'ARROW_DOWN': 40
};
/**
* Creates a dummy event to parse.
* Uses jQuery Event class constructor.
* @param {number} keyCode Key code of the key that is simulated.
* @param {object} opts Options that say if modifiers are pressed.
* @return {Event} Event to use.
*/
global.mockKeyboardEvent = mockKeyboardEvent = function(keyCode, opts) {
var options = opts || {},
isCtrl = !!options.ctrl,
isAlt = !!options.alt,
isShift = !!options.shift,
isMeta = !!options.meta,
keyCode = typeof keyCode === 'number' ? keyCode : keyCodes[keyCode],
event = {
shiftKey: isShift,
altKey: isAlt,
ctrlKey: isCtrl,
metaKey: isMeta,
keyCode: keyCode,
which: keyCode
};
return new $.Event('keydown', event);
};
})(window);
+43
View File
@@ -0,0 +1,43 @@
(function (global, $) {
/**
* Try to catch the `do` function every `interval` delay, until it succedes
* (does not throw an error) or a given `timout` time passed.
* If a `then` function is passed, it is called after `do` succeded.
* If a `catch` function is passed, it is called after each time `do` fails.
*
* @param {object} opts
* @param {object} opts
*/
global.tryInterval = function (opts) {
var _opts = $.extend({}, opts);
var totalTime = 0;
var interval = setInterval(function () {
var succeded = false;
var error = null;
totalTime += _opts.time;
try {
_opts.try();
succeded = true;
}
catch (err) { error = err; }
if (succeded) {
clearInterval(interval);
if (typeof _opts.then === 'function') _opts.then();
}
else if (totalTime > _opts.timeout) {
clearInterval(interval);
throw error;
}
else {
if (typeof _opts.catch === 'function') _opts.catch(error);
}
}, _opts.interval);
};
})(window, jQuery);
+51
View File
@@ -0,0 +1,51 @@
describe('Foundation box', function () {
var $html;
afterEach(function () {
if ($html) {
$html.remove();
}
});
describe('GetDimensions()', function () {
it('should be unable to get dimensions for window', function(done) {
try {
Foundation.Box.GetDimensions($("window"));
should.fail();
} catch (err) {
done();
}
});
it('should be unable to get dimensions for document', function(done) {
try {
Foundation.Box.GetDimensions($("document"));
should.fail();
} catch (err) {
done();
}
});
it('height and width of element', function () {
$html = $('<div id="rect-test" style="height: 100px;width:200px;"></div>').appendTo('body');
var dims = Foundation.Box.GetDimensions($("#rect-test"));
dims.width.should.equal(200);
dims.height.should.equal(100);
});
it('parent height of element', function () {
$html = $('<div style="height: 200px;"><div id="rect-test-parent" style="height: 100px;width:200px;"></div></div>').appendTo('body');
var dims = Foundation.Box.GetDimensions($("#rect-test-parent"));
dims.width.should.equal(200);
dims.height.should.equal(100);
dims.parentDims.height.should.equal(200);
});
});
});
+262
View File
@@ -0,0 +1,262 @@
describe('Keyboard util', function() {
/**
* Creates a dummy event to parse.
* Uses jQuery Event class constructor.
* @param {number} keyCode Key code of the key that is simulated.
* @param {object} opts Options that say if modifiers are pressed.
* @return {Event} Event to use.
*/
const createEvent = window.mockKeyboardEvent;
const keyCodes = {
'A': 65,
'TAB': 9,
'ENTER': 13,
'ESCAPE': 27,
'SPACE': 32,
'ARROW_LEFT': 37,
'ARROW_UP': 38,
'ARROW_RIGHT': 39,
'ARROW_DOWN': 40
};
afterEach(function() {
document.activeElement.blur();
});
it('exists on the Foundation API', function() {
(window.Foundation.Keyboard).should.be.an('object');
});
describe('parseKey()', function() {
it('returns the character pressed for a normal key', function() {
let event = createEvent(keyCodes['A']),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal('A');
});
it('returns the character pressed for special keys', function() {
for (let key in keyCodes) {
let keyCode = keyCodes[key];
let event = createEvent(keyCode),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal(key);
}
});
it('recognizes if CTRL was pressed', function() {
let event = createEvent(keyCodes['A'], {ctrl: true}),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal('CTRL_A');
});
it('recognizes if ALT was pressed', function() {
let event = createEvent(keyCodes['A'], {alt: true}),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal('ALT_A');
});
it('recognizes if SHIFT was pressed', function() {
let event = createEvent(keyCodes['A'], {shift: true}),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal('SHIFT_A');
});
it('recognizes if multiple modifiers were pressed', function() {
let event = createEvent(keyCodes['A'], {shift: true, alt: true, ctrl: true}),
parsedKey = Foundation.Keyboard.parseKey(event);
parsedKey.should.be.equal('ALT_CTRL_SHIFT_A');
});
});
describe('handleKey()', function() {
it('executes callback for given key event', function() {
let spy = sinon.spy();
// Register component
Foundation.Keyboard.register('MyComponent', {
'ESCAPE': 'close'
});
let event = createEvent(keyCodes['ESCAPE']);
Foundation.Keyboard.handleKey(event, 'MyComponent', {
close: () => {
spy();
}
});
spy.called.should.be.true;
});
it('executes handled callback for given key event', function() {
let spy = sinon.spy();
// Register component
Foundation.Keyboard.register('MyComponent', {
'ESCAPE': 'close'
});
let event = createEvent(keyCodes['ESCAPE']);
Foundation.Keyboard.handleKey(event, 'MyComponent', {
close: () => {
// stuff
},
handled: () => {
spy();
}
});
spy.called.should.be.true;
});
it('executes unhandled callback for given key event', function() {
let spy = sinon.spy();
// Register component
Foundation.Keyboard.register('MyComponent', {
});
let event = createEvent(keyCodes['ESCAPE']);
Foundation.Keyboard.handleKey(event, 'MyComponent', {
unhandled: () => {
spy();
}
});
spy.called.should.be.true;
});
});
describe('findFocusable()', function() {
it('finds focusable elements inside a container', function() {
let $html = $(`<div>
<a href="#">Link</a>
<button>Button</button>
</div>`).appendTo('body');
let $focusable = Foundation.Keyboard.findFocusable($html);
$focusable.length.should.be.equal(2);
$html.remove();
});
it('does not find hidden focusable elements', function() {
let $html = $(`<div>
<a style="display: none;" href="#">Link</a>
<button style="display: none;">Button</button>
</div>`).appendTo('body');
let $focusable = Foundation.Keyboard.findFocusable($html);
$focusable.length.should.be.equal(0);
$html.remove();
});
it('does not find disabled focusable elements', function() {
let $html = $(`<div>
<button disabled>Button</button>
</div>`).appendTo('body');
let $focusable = Foundation.Keyboard.findFocusable($html);
$focusable.length.should.be.equal(0);
$html.remove();
});
it('does not find focusable elements with negative tabindex', function() {
let $html = $(`<div>
<button tabindex="-1">Button</button>
</div>`).appendTo('body');
let $focusable = Foundation.Keyboard.findFocusable($html);
$focusable.length.should.be.equal(0);
$html.remove();
});
});
describe('trapFocus()', function() {
it('moves the focus to the first focusable element', function() {
let $html = $(`<div>
<a href="#">Link1</a>
<a href="#">Link2</a>
<a href="#">Link3</a>
</div>`).appendTo('body');
Foundation.Keyboard.trapFocus($html);
$html.find('a').last().focus();
let event = createEvent(keyCodes['TAB']);
$(document.activeElement).trigger(event);
document.activeElement.should.be.equal($html.find('a').eq(0)[0]);
$html.remove();
});
it('moves the focus to the last focusable element', function() {
let $html = $(`<div>
<a href="#">Link1</a>
<a href="#">Link2</a>
<a href="#">Link3</a>
</div>`).appendTo('body');
Foundation.Keyboard.trapFocus($html);
$html.find('a').first().focus();
let event = createEvent(keyCodes['TAB'], {shift: true});
$(document.activeElement).trigger(event);
document.activeElement.should.be.equal($html.find('a').eq(2)[0]);
$html.remove();
});
});
describe('releaseFocus()', function() {
it('stops trapping the focus at the end', function() {
let $html = $(`<div>
<a href="#">Link1</a>
<a href="#">Link2</a>
<a href="#">Link3</a>
</div>`).appendTo('body');
Foundation.Keyboard.trapFocus($html);
$html.find('a').last().focus();
Foundation.Keyboard.releaseFocus($html);
let event = createEvent(keyCodes['TAB']);
$(document.activeElement).trigger(event);
document.activeElement.should.not.be.equal($html.find('a').eq(0)[0]);
$html.remove();
});
it('stops trapping the focus at the top', function() {
let $html = $(`<div>
<a href="#">Link1</a>
<a href="#">Link2</a>
<a href="#">Link3</a>
</div>`).appendTo('body');
Foundation.Keyboard.trapFocus($html);
$html.find('a').first().focus();
Foundation.Keyboard.releaseFocus($html);
let event = createEvent(createEvent(keyCodes['TAB'], {shift: true}));
$(document.activeElement).trigger(event);
document.activeElement.should.not.be.equal($html.find('a').eq(2)[0]);
$html.remove();
});
});
});