VulpesOS/gaia/apps/sharedtest/test/unit/option_menu_test.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

231 lines
6.3 KiB
JavaScript
Executable file

/*global OptionMenu, MockL10n, TransitionEvent */
'use strict';
require('/shared/test/unit/mocks/mock_l10n.js');
require('/shared/js/option_menu.js');
suite('OptionMenu', function() {
var options, menu, formHeader, formSection, realL10n;
suiteSetup(function() {
options = {
id: 'menu-fixture',
header: 'Text Header',
section: 'Text Section',
classes: ['class1', 'class2'],
items: [
{
name: 'test',
method: function(param) {
},
params: ['foo']
},
{
l10nId: 'cancel',
l10nArgs: { test: true }
}
]
};
realL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
});
suiteTeardown(function() {
navigator.mozL10n = realL10n;
});
setup(function() {
this.sinon.spy(navigator.mozL10n, 'setAttributes');
menu = new OptionMenu(options);
formHeader = menu.form.querySelector('header');
formSection = menu.form.querySelector('section');
});
teardown(function() {
var fixture = document.getElementById('menu-fixture');
if (fixture) {
document.body.removeChild(fixture);
}
});
suite('Instance', function() {
test('OptionMenu', function() {
assert.ok(OptionMenu);
assert.ok(OptionMenu.prototype.show);
assert.ok(OptionMenu.prototype.hide);
});
suite('menu.show()', function() {
setup(function() {
this.sinon.stub(menu.form, 'focus');
this.sinon.stub(HTMLElement.prototype, 'blur');
menu.show();
});
test('appends element to body', function() {
assert.equal(
menu.form, document.body.lastElementChild
);
});
test('Redundant shows have no effect', function() {
sinon.spy(document.body, 'appendChild');
menu.show();
sinon.assert.notCalled(document.body.appendChild);
});
test('Prevent pointer events and focus', function() {
menu.show();
sinon.assert.called(HTMLElement.prototype.blur);
assert.isTrue(document.body.classList.contains('dialog-animating'));
var transitionend = new TransitionEvent('transitionend', {
bubbles: true,
propertyName: 'transform'
});
menu.form.dispatchEvent(transitionend);
assert.isFalse(document.body.classList.contains('dialog-animating'));
sinon.assert.called(menu.form.focus);
});
suite('menu.hide()', function() {
setup(function() {
menu.hide();
});
test('hiding is delayed by animation', function() {
assert.notEqual(menu.form.parentElement, null);
});
test('removes element from DOM after transitionend', function() {
var transitionend =
new CustomEvent('transitionend', { target: menu.form });
menu.form.dispatchEvent(transitionend);
assert.equal(menu.form.parentElement, null);
});
});
});
});
suite('Display', function() {
test('header: text', function() {
assert.equal(
formHeader.textContent, 'Text Header'
);
});
test('header: element', function() {
options.header = document.createElement('header');
options.header.textContent = 'Element Header';
menu = new OptionMenu(options);
formHeader = menu.form.firstElementChild;
assert.equal(
formHeader.textContent, 'Element Header'
);
});
test('header: none', function() {
options.header = null;
menu = new OptionMenu(options);
assert.isNull(menu.form.querySelector('header'));
});
test('section: text', function() {
assert.equal(
formSection.textContent, 'Text Section'
);
});
test('section: element', function() {
options.section = document.createElement('section');
options.section.textContent = 'Element Section';
menu = new OptionMenu(options);
formSection = menu.form.firstElementChild;
assert.equal(
formSection.textContent, 'Element Section'
);
});
test('section: none', function() {
options.section = null;
menu = new OptionMenu(options);
assert.isNull(menu.form.querySelector('section'));
});
test('style doesn\'t affect confirm dialogs', function(next) {
var style = document.createElement('style');
style.textContent = '@import "../../../../shared/style/option_menu.css"';
var loaded = setInterval(function() {
try {
// We're waiting for an @import stylesheet to load, so wait for the
// inner set of cssRules.
style.sheet.cssRules[0].styleSheet.cssRules;
clearInterval(loaded);
} catch (e) {
// Waiting for stylesheet to load
} finally {
// Clear the interval again just in case we threw before calling
// clearInterval() the first time. This is necessary so we don't call
// the done() function multiple times.
clearInterval(loaded);
var form = document.createElement('form');
form.setAttribute('role', 'dialog');
form.setAttribute('data-type', 'confirm');
document.body.appendChild(form);
var compStyle = window.getComputedStyle(form);
assert.notEqual(compStyle.visibility, 'hidden');
next();
}
}, 10);
document.body.appendChild(style);
});
});
suite('Options', function() {
var buttons;
setup(function() {
buttons = menu.form.querySelectorAll('button');
});
test('Buttons', function() {
Array.forEach(buttons, (button) => {
assert.equal(button.type, 'button');
});
assert.equal(buttons.length, 2);
});
test('Button Text', function() {
assert.equal(buttons[0].textContent, options.items[0].name);
});
test('Localized button', function() {
sinon.assert.calledWith(navigator.mozL10n.setAttributes, buttons[1],
options.items[1].l10nId, options.items[1].l10nArgs);
});
test('classes', function() {
assert.ok(menu.form.classList.contains('class1'));
assert.ok(menu.form.classList.contains('class2'));
});
});
suite('Behaviours', function() {
test('Fat fingering does not hide menu', function() {
menu.show();
menu.form.click();
assert.equal(
menu.form, document.body.lastElementChild
);
});
});
});