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.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
305
gaia/apps/calendar/test/unit/views/advanced_settings_test.js
Executable file
305
gaia/apps/calendar/test/unit/views/advanced_settings_test.js
Executable file
|
|
@ -0,0 +1,305 @@
|
|||
/* global suiteTemplate, MockMozIntl */
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
require('/shared/elements/gaia-header/dist/gaia-header.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_intl.js');
|
||||
|
||||
var AccountTemplate = require('templates/account');
|
||||
var AdvancedSettings = require('views/advanced_settings');
|
||||
var Factory = require('test/support/factory');
|
||||
var core = require('core');
|
||||
var waitFor = require('test/support/wait_for');
|
||||
|
||||
require('dom!advanced_settings');
|
||||
|
||||
suite('Views.AdvancedSettings', function() {
|
||||
var subject;
|
||||
var template;
|
||||
var accountStore;
|
||||
var fixtures;
|
||||
var settings;
|
||||
var triggerEvent;
|
||||
|
||||
suiteSetup(function() {
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
window.mozIntl = MockMozIntl;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
fixtures = {
|
||||
a: Factory('account', {
|
||||
_id: 'a',
|
||||
providerType: 'Caldav'
|
||||
}),
|
||||
|
||||
b: Factory('account', {
|
||||
_id: 'b',
|
||||
providerType: 'Caldav'
|
||||
}),
|
||||
|
||||
// expected not to be displayed.
|
||||
notRendered: Factory('account', {
|
||||
_id: 'c',
|
||||
providerType: 'Local'
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
var db;
|
||||
suiteTemplate('advanced-settings', {
|
||||
id: 'advanced-settings-view'
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
db = core.db;
|
||||
|
||||
template = AccountTemplate;
|
||||
subject = new AdvancedSettings();
|
||||
|
||||
accountStore = core.storeFactory.get('Account');
|
||||
settings = core.storeFactory.get('Setting');
|
||||
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var trans = db.transaction('accounts', 'readwrite');
|
||||
|
||||
for (var key in fixtures) {
|
||||
accountStore.persist(fixtures[key], trans);
|
||||
}
|
||||
|
||||
trans.oncomplete = function() {
|
||||
done();
|
||||
};
|
||||
|
||||
trans.onerror = function(e) {
|
||||
done(e);
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('#accountList', function() {
|
||||
assert.ok(subject.accountList);
|
||||
});
|
||||
|
||||
test('#syncFrequency', function() {
|
||||
var freq = subject.syncFrequency;
|
||||
assert.ok(freq);
|
||||
});
|
||||
|
||||
test('#element', function() {
|
||||
var el = document.querySelector(subject.selectors.element);
|
||||
assert.ok(el);
|
||||
|
||||
assert.equal(subject.element, el);
|
||||
});
|
||||
|
||||
suite('#_initEvents', function() {
|
||||
var children;
|
||||
|
||||
setup(function(done) {
|
||||
children = subject.accountList.children;
|
||||
subject._initEvents();
|
||||
waitFor(() => children.length === 2, done);
|
||||
});
|
||||
|
||||
suite('syncFrequency', function() {
|
||||
var expected;
|
||||
|
||||
setup(function(done) {
|
||||
settings.getValue('syncFrequency', function(err, value) {
|
||||
expected = String(value);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('selected value should match store', function(done) {
|
||||
assert.ok(expected, 'expected');
|
||||
waitFor(() => subject.syncFrequency.value === expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('account with error', function() {
|
||||
var withError;
|
||||
|
||||
setup(function(done) {
|
||||
withError = Factory('account', {
|
||||
_id: 'with-error',
|
||||
providerType: 'Caldav',
|
||||
error: {}
|
||||
});
|
||||
accountStore.persist(withError);
|
||||
waitFor(() => children.length === 3, done);
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
accountStore.remove(withError._id);
|
||||
waitFor(() => children.length === 2, done);
|
||||
});
|
||||
|
||||
test('adds error class', function() {
|
||||
assert.ok(subject.accountList.querySelector('.error'));
|
||||
});
|
||||
|
||||
test('| update', function(done) {
|
||||
accountStore.persist(Factory('account', {
|
||||
_id: 'with-error',
|
||||
providerType: 'Caldav',
|
||||
error: undefined
|
||||
}));
|
||||
|
||||
waitFor(() => {
|
||||
return subject.accountList.querySelector('.error') == null;
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('| remove', function(done) {
|
||||
accountStore.remove(withError._id);
|
||||
waitFor(() => children.length === 2, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('local provider', function() {
|
||||
setup(function(done) {
|
||||
accountStore.persist(Factory('account', {
|
||||
providerType: 'Local'
|
||||
}), done);
|
||||
});
|
||||
test('does not add account', function() {
|
||||
assert.lengthOf(children, 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('#handleSettingUiChange', function() {
|
||||
var calledWith;
|
||||
var originalSet;
|
||||
|
||||
setup(function() {
|
||||
subject._initEvents();
|
||||
calledWith = 'notcalled';
|
||||
originalSet = settings.set;
|
||||
settings.set = function(name, value) {
|
||||
if (name === 'syncFrequency') {
|
||||
calledWith = value;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
settings.set = originalSet;
|
||||
});
|
||||
|
||||
function change(name, value) {
|
||||
var el = subject[name];
|
||||
el.value = value;
|
||||
triggerEvent(el, 'change');
|
||||
}
|
||||
|
||||
suite('syncFrequency', function() {
|
||||
test('null', function() {
|
||||
change('syncFrequency', 'null');
|
||||
assert.equal(calledWith, null);
|
||||
});
|
||||
|
||||
test('numeric', function() {
|
||||
change('syncFrequency', '30');
|
||||
assert.equal(calledWith, 30);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('on syncFrequencyChange', function() {
|
||||
var select;
|
||||
|
||||
suite('syncFrequency', function() {
|
||||
setup(function() {
|
||||
select = subject.syncFrequency;
|
||||
subject._initEvents();
|
||||
});
|
||||
|
||||
test('numeric 15', function(done) {
|
||||
select.value = 'null';
|
||||
settings.emit('syncFrequencyChange', 15);
|
||||
waitFor(() => select.value === '15', done);
|
||||
});
|
||||
|
||||
test('null', function(done) {
|
||||
select.value = '15';
|
||||
settings.emit('syncFrequencyChange', null);
|
||||
waitFor(() => select.value === 'null', done);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('#render', function() {
|
||||
var list;
|
||||
|
||||
var expectedEventAlarm = -300;
|
||||
var expectedAllDayAlarm = 32400;
|
||||
|
||||
setup(function(done) {
|
||||
var pending = 2;
|
||||
|
||||
settings.set('standardAlarmDefault', expectedEventAlarm, next);
|
||||
settings.set('alldayAlarmDefault', expectedAllDayAlarm, next);
|
||||
|
||||
function next() {
|
||||
if (!(--pending)) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// stage error
|
||||
setup(function(done) {
|
||||
fixtures.b.error = {};
|
||||
accountStore.persist(fixtures.b, done);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
list = subject.accountList;
|
||||
|
||||
subject.render().then(done);
|
||||
});
|
||||
|
||||
test('alarm select populated', function() {
|
||||
assert.equal(
|
||||
subject.standardAlarmLabel.querySelectorAll('select').length,
|
||||
1
|
||||
);
|
||||
assert.equal(
|
||||
subject.alldayAlarmLabel.querySelectorAll('select').length,
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
test('alarms set to stored value', function() {
|
||||
assert.equal(
|
||||
subject.standardAlarm.value, expectedEventAlarm,
|
||||
'event alarm set to stored value'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
subject.alldayAlarm.value, expectedAllDayAlarm,
|
||||
'event alarm set to stored value'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
149
gaia/apps/calendar/test/unit/views/create_account_test.js
Executable file
149
gaia/apps/calendar/test/unit/views/create_account_test.js
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var AccountTemplate = require('templates/account');
|
||||
var CreateAccount = require('views/create_account');
|
||||
var Presets = require('common/presets');
|
||||
var core = require('core');
|
||||
|
||||
suite('Views.CreateAccount', function() {
|
||||
var subject;
|
||||
var template;
|
||||
var storeFactory;
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="create-account-view">',
|
||||
'<gaia-header id="create-account-header" action="back">',
|
||||
'<h1>Add an account</h1>',
|
||||
'</gaia-header>',
|
||||
'<ul id="create-account-presets"></ul>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
storeFactory = core.storeFactory;
|
||||
template = AccountTemplate;
|
||||
subject = new CreateAccount();
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
subject.destroy();
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('#element', function() {
|
||||
var el = document.querySelector(subject.selectors.element);
|
||||
assert.ok(el);
|
||||
|
||||
assert.equal(subject.element, el);
|
||||
});
|
||||
|
||||
test('#accounts', function() {
|
||||
assert.equal(
|
||||
subject.accounts,
|
||||
document.querySelector(subject.selectors.accounts)
|
||||
);
|
||||
});
|
||||
|
||||
suite('#_initEvents', function() {
|
||||
setup(function(done) {
|
||||
subject.render = done;
|
||||
subject._initEvents();
|
||||
});
|
||||
|
||||
test('when an account is added', function(done) {
|
||||
var store = storeFactory.get('Account');
|
||||
subject.render = done;
|
||||
store.emit('add');
|
||||
});
|
||||
|
||||
test('when an account is removed', function(done) {
|
||||
var store = storeFactory.get('Account');
|
||||
subject.render = done;
|
||||
store.emit('remove');
|
||||
});
|
||||
});
|
||||
|
||||
suite('#render', function() {
|
||||
setup(function() {
|
||||
subject.accounts.innerHTML = '__MARKER__';
|
||||
});
|
||||
|
||||
suite('default calendar presets', function() {
|
||||
var presets;
|
||||
|
||||
setup(function(done) {
|
||||
presets = Object.keys(Presets);
|
||||
subject.render().then(done).catch(done);
|
||||
});
|
||||
|
||||
test('each preset is displayed', function() {
|
||||
var html = subject.accounts.innerHTML;
|
||||
|
||||
assert.ok(html);
|
||||
|
||||
presets.forEach(function(val) {
|
||||
assert.include(
|
||||
html,
|
||||
val
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('with preset marked for single use', function() {
|
||||
setup(function(done) {
|
||||
subject.presets = {
|
||||
'one': {
|
||||
singleUse: true,
|
||||
providerType: 'local'
|
||||
},
|
||||
'two': {
|
||||
singleUse: true,
|
||||
providerType: 'local'
|
||||
}
|
||||
};
|
||||
|
||||
var accountStore = storeFactory.get('Account');
|
||||
|
||||
accountStore.persist({ preset: 'one' }, function() {
|
||||
subject.render().then(done).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
test('hides used single use presets', function() {
|
||||
assert.ok(
|
||||
subject.accounts.innerHTML.indexOf('__MARKER__') === -1
|
||||
);
|
||||
|
||||
var html = subject.accounts.innerHTML;
|
||||
assert.ok(html);
|
||||
var hasLocal = (html.indexOf('local') !== -1);
|
||||
|
||||
assert.isFalse(
|
||||
hasLocal,
|
||||
'single use presets should not be displayed'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
475
gaia/apps/calendar/test/unit/views/current_time_test.js
Executable file
475
gaia/apps/calendar/test/unit/views/current_time_test.js
Executable file
|
|
@ -0,0 +1,475 @@
|
|||
/* global MockMozIntl */
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_moz_intl.js');
|
||||
|
||||
var CurrentTime = require('views/current_time');
|
||||
|
||||
suite('Views.CurrentTime', function() {
|
||||
var subject;
|
||||
var container;
|
||||
var timespan;
|
||||
var realMozIntl;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozIntl = window.mozIntl;
|
||||
window.mozIntl = MockMozIntl;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var startOfDay = new Date();
|
||||
startOfDay.setHours(0, 0, 0, 0);
|
||||
|
||||
var endOfDay = new Date();
|
||||
endOfDay.setHours(24, 0, 0, 0);
|
||||
|
||||
// mocks the Calendar.TimeSpan API needed by CurrentTime
|
||||
timespan = {
|
||||
start: startOfDay,
|
||||
end: endOfDay
|
||||
};
|
||||
timespan.contains = timespan.containsNumeric = function(date) {
|
||||
return date >= timespan.start && date <= timespan.end;
|
||||
};
|
||||
|
||||
container = {
|
||||
'appendChild': sinon.spy(),
|
||||
'removeChild': sinon.spy()
|
||||
};
|
||||
|
||||
subject = new CurrentTime({ container: container, timespan: timespan });
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.mozIntl = realMozIntl;
|
||||
});
|
||||
|
||||
suite('#_create', function() {
|
||||
setup(function() {
|
||||
subject._create();
|
||||
});
|
||||
|
||||
test('create and append element to DOM', function() {
|
||||
assert.ok(subject.element, 'element');
|
||||
assert.include(
|
||||
subject.element.className,
|
||||
'current-time',
|
||||
'className'
|
||||
);
|
||||
assert.equal(subject.element.getAttribute('aria-hidden'), 'true');
|
||||
assert.ok(
|
||||
container.appendChild.calledWithExactly(subject.element),
|
||||
'append to DOM'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#activate', function() {
|
||||
var contains;
|
||||
|
||||
setup(function() {
|
||||
contains = sinon.stub(timespan, 'containsNumeric');
|
||||
sinon.stub(subject, '_create');
|
||||
sinon.stub(subject, '_tick');
|
||||
sinon.stub(subject, '_maybeActivateInTheFuture');
|
||||
subject.element = {
|
||||
classList: {
|
||||
add: sinon.stub()
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
contains.restore();
|
||||
subject._create.restore();
|
||||
subject._tick.restore();
|
||||
subject._maybeActivateInTheFuture.restore();
|
||||
delete subject.element;
|
||||
});
|
||||
|
||||
test('create and setup tick if date is inside timespan', function() {
|
||||
contains.returns(true);
|
||||
subject.activate();
|
||||
|
||||
assert.ok(
|
||||
timespan.containsNumeric.calledOnce,
|
||||
'timespan.containsNumeric'
|
||||
);
|
||||
assert.ok(
|
||||
!subject._maybeActivateInTheFuture.called,
|
||||
'_maybeActivateInTheFuture'
|
||||
);
|
||||
assert.ok(
|
||||
subject._create.calledOnce,
|
||||
'_create'
|
||||
);
|
||||
assert.ok(
|
||||
subject._tick.calledOnce,
|
||||
'_tick'
|
||||
);
|
||||
assert.ok(
|
||||
subject.element.classList.add.calledWithExactly('active'),
|
||||
'add active class'
|
||||
);
|
||||
});
|
||||
|
||||
test('call _maybeActivateInTheFuture if outside timespan', function() {
|
||||
contains.returns(false);
|
||||
subject.activate();
|
||||
assert.ok(
|
||||
subject._maybeActivateInTheFuture.calledOnce
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_maybeActivateInTheFuture', function() {
|
||||
var clock;
|
||||
var start;
|
||||
var offset = 24 * 60 * 60 * 1000;
|
||||
|
||||
setup(function() {
|
||||
clock = sinon.useFakeTimers();
|
||||
start = timespan.start;
|
||||
timespan.start = Date.now() + offset;
|
||||
sinon.stub(subject, 'activate');
|
||||
sinon.stub(subject, '_clearInterval');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
timespan.start = start;
|
||||
subject.activate.restore();
|
||||
subject._clearInterval.restore();
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('call activate after timeout', function() {
|
||||
subject._maybeActivateInTheFuture();
|
||||
assert.ok(
|
||||
!subject.activate.called,
|
||||
'only call activate after timeout'
|
||||
);
|
||||
assert.ok(
|
||||
subject._clearInterval.calledOnce,
|
||||
'clear previous timeout'
|
||||
);
|
||||
clock.tick(offset);
|
||||
assert.ok(
|
||||
subject.activate.calledOnce,
|
||||
'call activate after timeout'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_render', function() {
|
||||
var clock;
|
||||
var date;
|
||||
var element;
|
||||
|
||||
setup(function() {
|
||||
date = new Date(2014, 4, 22, 5, 15);
|
||||
clock = sinon.useFakeTimers(+date);
|
||||
element = subject.element;
|
||||
sinon.stub(subject, '_checkOverlap');
|
||||
subject.element = {
|
||||
textContent: null,
|
||||
style: {
|
||||
top: null
|
||||
},
|
||||
dataset: {
|
||||
date: null,
|
||||
l10nDateFormat: null
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
clock.restore();
|
||||
subject.element = element;
|
||||
subject._checkOverlap.restore();
|
||||
});
|
||||
|
||||
test('should update position and time', function() {
|
||||
subject._render();
|
||||
assert.equal(subject.element.id, 'current-time-indicator');
|
||||
assert.deepEqual(
|
||||
subject.element,
|
||||
{
|
||||
textContent: '5:15 AM',
|
||||
style: {
|
||||
top: '21.875%'
|
||||
},
|
||||
id: 'current-time-indicator',
|
||||
dataset: {
|
||||
date: date,
|
||||
l10nDateFormat: 'current-time'
|
||||
}
|
||||
}
|
||||
);
|
||||
assert.ok(
|
||||
subject._checkOverlap.calledOnce,
|
||||
'call _checkOverlap once'
|
||||
);
|
||||
assert.ok(
|
||||
subject._checkOverlap.calledWithExactly(5),
|
||||
'call _checkOverlap with current hour'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_tick', function() {
|
||||
var clock;
|
||||
|
||||
setup(function() {
|
||||
sinon.stub(subject, '_render');
|
||||
sinon.stub(subject, '_clearInterval');
|
||||
sinon.stub(subject, 'deactivate');
|
||||
sinon.spy(subject, '_tick');
|
||||
sinon.stub(timespan, 'contains');
|
||||
clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject._render.restore();
|
||||
subject._clearInterval.restore();
|
||||
subject.deactivate.restore();
|
||||
subject._tick.restore();
|
||||
timespan.contains.restore();
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('inside range', function() {
|
||||
timespan.contains.returns(true);
|
||||
subject._tick();
|
||||
assert.ok(
|
||||
subject._clearInterval.calledOnce,
|
||||
'_clearInterval'
|
||||
);
|
||||
assert.ok(
|
||||
!subject.deactivate.called,
|
||||
'deactivate'
|
||||
);
|
||||
assert.ok(
|
||||
subject._render.calledOnce,
|
||||
'_render'
|
||||
);
|
||||
|
||||
// should call tick every minute
|
||||
assert.ok(
|
||||
subject._tick.calledOnce,
|
||||
'_tick #1'
|
||||
);
|
||||
clock.tick(60000);
|
||||
assert.ok(
|
||||
subject._tick.calledTwice,
|
||||
'_tick #2'
|
||||
);
|
||||
clock.tick(60000);
|
||||
assert.ok(
|
||||
subject._tick.calledThrice,
|
||||
'_tick #3'
|
||||
);
|
||||
});
|
||||
|
||||
test('outside range', function() {
|
||||
timespan.contains.returns(false);
|
||||
subject._tick();
|
||||
|
||||
assert.ok(
|
||||
subject._clearInterval.calledOnce,
|
||||
'_clearInterval'
|
||||
);
|
||||
assert.ok(
|
||||
subject.deactivate.calledOnce,
|
||||
'deactivate'
|
||||
);
|
||||
assert.ok(
|
||||
!subject._render.called,
|
||||
'_render'
|
||||
);
|
||||
|
||||
// should not call tick multiple times
|
||||
assert.ok(
|
||||
subject._tick.calledOnce,
|
||||
'_tick #1'
|
||||
);
|
||||
clock.tick(60000);
|
||||
assert.ok(
|
||||
subject._tick.calledOnce,
|
||||
'_tick #2'
|
||||
);
|
||||
clock.tick(60000);
|
||||
assert.ok(
|
||||
subject._tick.calledOnce,
|
||||
'_tick #3'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_checkOverlap', function() {
|
||||
var hour2;
|
||||
|
||||
function HourElement(top, right, left, bottom) {
|
||||
this.getBoundingClientRect = function() {
|
||||
return {
|
||||
top: top,
|
||||
right: right,
|
||||
left: left,
|
||||
bottom: bottom
|
||||
};
|
||||
};
|
||||
this.classList = {
|
||||
toggle: sinon.spy(),
|
||||
remove: sinon.spy()
|
||||
};
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
hour2 = new HourElement(40, 50, 10, 60);
|
||||
|
||||
subject._container = {
|
||||
querySelector: sinon.stub()
|
||||
.withArgs('.hour-2 .display-hour')
|
||||
.returns(hour2)
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject._container = container;
|
||||
delete subject.element;
|
||||
});
|
||||
|
||||
suite('> overlaps', function() {
|
||||
setup(function() {
|
||||
subject.element = {
|
||||
getBoundingClientRect: function() {
|
||||
return {
|
||||
top: 55,
|
||||
right: 300,
|
||||
left: 0,
|
||||
bottom: 65
|
||||
};
|
||||
}
|
||||
};
|
||||
subject._previousOverlap = new HourElement(10, 10, 30, 30);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete subject.element;
|
||||
delete subject._previousOverlap;
|
||||
});
|
||||
|
||||
test('hide overlapping hour', function() {
|
||||
subject._checkOverlap(2);
|
||||
assert.ok(
|
||||
hour2.classList.toggle.calledWithExactly('is-hidden', true),
|
||||
'should hide second hour'
|
||||
);
|
||||
assert.strictEqual(
|
||||
subject._previousOverlap,
|
||||
hour2,
|
||||
'update _previousOverlap'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> doesn\'t overlap', function() {
|
||||
setup(function() {
|
||||
subject.element = {
|
||||
getBoundingClientRect: function() {
|
||||
return {
|
||||
top: 105,
|
||||
right: 300,
|
||||
left: 0,
|
||||
bottom: 115
|
||||
};
|
||||
}
|
||||
};
|
||||
subject._previousOverlap = hour2;
|
||||
});
|
||||
|
||||
test('should not hide hour', function() {
|
||||
subject._checkOverlap(2);
|
||||
assert.ok(
|
||||
hour2.classList.toggle.calledWithExactly('is-hidden', false),
|
||||
'should not hide second hour'
|
||||
);
|
||||
assert.ok(
|
||||
!hour2.classList.remove.called,
|
||||
'should display second hour'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('#deactivate', function() {
|
||||
suite('> with element', function() {
|
||||
setup(function() {
|
||||
sinon.stub(subject, '_clearInterval');
|
||||
subject.element = {
|
||||
classList: {
|
||||
remove: sinon.stub()
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject._clearInterval.restore();
|
||||
delete subject.element;
|
||||
});
|
||||
|
||||
test('should clear the interval & remove active class', function() {
|
||||
subject.deactivate();
|
||||
assert.ok(subject._clearInterval.calledOnce, '_clearInterval');
|
||||
assert.ok(
|
||||
subject.element.classList.remove.calledWithExactly('active'),
|
||||
'remove active class'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// element is only created after first activate call and we need to ensure
|
||||
// deactivate still works even without an element
|
||||
suite('> without element', function() {
|
||||
setup(function() {
|
||||
sinon.stub(subject, '_clearInterval');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject._clearInterval.restore();
|
||||
});
|
||||
|
||||
test('should clear the interval', function() {
|
||||
assert.ok(!subject.element, 'no element');
|
||||
subject.deactivate();
|
||||
assert.ok(subject._clearInterval.calledOnce, '_clearInterval');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('#destroy', function() {
|
||||
var el;
|
||||
|
||||
setup(function() {
|
||||
el = subject.element = {
|
||||
classList: {
|
||||
remove: sinon.stub()
|
||||
}
|
||||
};
|
||||
sinon.stub(subject, 'deactivate');
|
||||
subject._previousOverlap = {};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.deactivate.restore();
|
||||
});
|
||||
|
||||
test('stop timer, remove element', function() {
|
||||
subject.destroy();
|
||||
assert.ok(subject.deactivate.calledOnce, 'deactivate');
|
||||
assert.ok(container.removeChild.calledWithExactly(el), 'removeChild');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
24
gaia/apps/calendar/test/unit/views/errors_test.js
Executable file
24
gaia/apps/calendar/test/unit/views/errors_test.js
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var Errors = require('views/errors');
|
||||
var core = require('core');
|
||||
|
||||
suite('Views.Errors', function() {
|
||||
var subject, errorName;
|
||||
|
||||
setup(function() {
|
||||
subject = new Errors();
|
||||
|
||||
subject.showErrors = function(list) {
|
||||
errorName = list[0].name;
|
||||
};
|
||||
});
|
||||
|
||||
test('offline event', function() {
|
||||
core.syncController.emit('offline');
|
||||
assert.deepEqual(errorName, 'offline');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
331
gaia/apps/calendar/test/unit/views/event_base_test.js
Executable file
331
gaia/apps/calendar/test/unit/views/event_base_test.js
Executable file
|
|
@ -0,0 +1,331 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
require('/shared/elements/gaia-header/dist/gaia-header.js');
|
||||
var EventBase = require('views/event_base');
|
||||
var EventModel = require('models/event');
|
||||
var View = require('view');
|
||||
var router = require('router');
|
||||
|
||||
suite('Views.EventBase', function() {
|
||||
var core;
|
||||
var subject;
|
||||
var triggerEvent;
|
||||
var last = router.last;
|
||||
|
||||
function hasClass(value) {
|
||||
return subject.element.classList.contains(value);
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
core = testSupport.calendar.core();
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
last = router.last;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
router.last = last;
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="event-test">',
|
||||
'<gaia-header id="event-test-header" action="cancel">',
|
||||
'<button class="primary">primary</button>',
|
||||
'</gaia-header>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
subject = new EventBase({
|
||||
selectors: {
|
||||
element: '#event-test',
|
||||
header: '#event-test-header',
|
||||
primaryButton: '#event-test .primary'
|
||||
}
|
||||
});
|
||||
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
// setup this.account / this.calendar
|
||||
testSupport.calendar.accountEnvironment();
|
||||
|
||||
// setup this.event / this.busytime
|
||||
testSupport.calendar.eventEnvironment();
|
||||
|
||||
teardown(function(done) {
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts', 'calendars', 'events', 'busytimes'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.instanceOf(subject, View);
|
||||
assert.instanceOf(subject, EventBase);
|
||||
|
||||
assert.ok(subject._els, 'has elements');
|
||||
});
|
||||
|
||||
test('.primaryButton', function() {
|
||||
assert.ok(subject.primaryButton);
|
||||
});
|
||||
|
||||
test('.header', function() {
|
||||
assert.ok(subject.header);
|
||||
});
|
||||
|
||||
test('.fieldRoot', function() {
|
||||
assert.ok(subject.fieldRoot);
|
||||
assert.equal(subject.fieldRoot, subject.element);
|
||||
});
|
||||
|
||||
test('.uiSelector', function() {
|
||||
assert.ok(subject.uiSelector);
|
||||
});
|
||||
|
||||
suite('#_useModel', function() {
|
||||
var callsUpdateUI;
|
||||
setup(function() {
|
||||
callsUpdateUI = false;
|
||||
subject._updateUI = function() {
|
||||
callsUpdateUI = true;
|
||||
};
|
||||
});
|
||||
|
||||
test('readonly', function() {
|
||||
var record = {
|
||||
busytime: this.busytime,
|
||||
event: this.event,
|
||||
capabilities: { canUpdate: false }
|
||||
};
|
||||
|
||||
subject._useModel(record);
|
||||
assert.isTrue(hasClass(subject.READONLY), 'is readonly');
|
||||
assert.isTrue(callsUpdateUI, 'updates ui');
|
||||
});
|
||||
|
||||
test('normal', function() {
|
||||
var record = {
|
||||
busytime: this.busytime,
|
||||
event: this.event,
|
||||
calendar: { _id: this.event.calendarId },
|
||||
capabilities: { canUpdate: true }
|
||||
};
|
||||
|
||||
subject._useModel(record);
|
||||
assert.equal(
|
||||
subject.originalCalendar._id,
|
||||
record.event.calendarId
|
||||
);
|
||||
assert.isTrue(callsUpdateUI, 'updates ui');
|
||||
assert.isFalse(hasClass(subject.READONLY), 'is readonly');
|
||||
});
|
||||
});
|
||||
|
||||
suite('#dispatch', function() {
|
||||
var classList;
|
||||
|
||||
setup(function() {
|
||||
classList = subject.element.classList;
|
||||
});
|
||||
|
||||
suite('create', function() {
|
||||
var date = new Date();
|
||||
date.setDate(date.getDate() + 1);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
date.setMilliseconds(0);
|
||||
|
||||
var headerFontSize;
|
||||
|
||||
setup(function(done) {
|
||||
headerFontSize = this.sinon.stub(subject.header, 'runFontFitSoon');
|
||||
|
||||
core.timeController.move(date);
|
||||
subject.dispatch({ params: {} });
|
||||
|
||||
subject.ondispatch = done;
|
||||
});
|
||||
|
||||
test('display', function() {
|
||||
// Updates the header font size.
|
||||
sinon.assert.calledOnce(headerFontSize);
|
||||
|
||||
// class details
|
||||
assert.isTrue(classList.contains(subject.CREATE), 'has create class');
|
||||
assert.isFalse(
|
||||
classList.contains(subject.UPDATE),
|
||||
'has update class'
|
||||
);
|
||||
|
||||
// model
|
||||
assert.instanceOf(
|
||||
subject.event,
|
||||
EventModel
|
||||
);
|
||||
|
||||
// expected model time
|
||||
var expectedStart = new Date(date.valueOf());
|
||||
var expectedEnd = new Date(expectedStart.valueOf());
|
||||
expectedEnd.setHours(expectedStart.getHours() + 1);
|
||||
|
||||
assert.deepEqual(subject.event.startDate, expectedStart);
|
||||
assert.deepEqual(subject.event.endDate, expectedEnd);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('/add returnTo', function() {
|
||||
router.last = {
|
||||
path: '/event/add/'
|
||||
};
|
||||
|
||||
subject.dispatch({ params: {} });
|
||||
assert.equal(subject.returnTo(), subject.DEFAULT_VIEW);
|
||||
});
|
||||
|
||||
test('/advanced-settings returnTo', function() {
|
||||
router.last = {
|
||||
path: '/advanced-settings/'
|
||||
};
|
||||
|
||||
subject.dispatch({ params: {} });
|
||||
assert.strictEqual(subject.returnTo(), subject.DEFAULT_VIEW);
|
||||
});
|
||||
|
||||
test('/day returnTo', function() {
|
||||
router.last = {
|
||||
path: '/day/'
|
||||
};
|
||||
|
||||
subject.dispatch({ params: {} });
|
||||
assert.strictEqual(subject.returnTo(), '/day/');
|
||||
});
|
||||
|
||||
suite('update', function() {
|
||||
setup(function(done) {
|
||||
subject.ondispatch = done;
|
||||
subject.dispatch({
|
||||
params: { id: this.busytime._id }
|
||||
});
|
||||
|
||||
assert.ok(
|
||||
subject.element.classList.contains(subject.LOADING),
|
||||
'is loading'
|
||||
);
|
||||
});
|
||||
|
||||
test('is done loading', function() {
|
||||
assert.ok(
|
||||
!subject.element.classList.contains(subject.LOADING)
|
||||
);
|
||||
});
|
||||
|
||||
test('existing model', function() {
|
||||
assert.isFalse(classList.contains(subject.CREATE), 'has create class');
|
||||
assert.isTrue(classList.contains(subject.UPDATE), 'has update class');
|
||||
|
||||
assert.deepEqual(
|
||||
subject.busytime,
|
||||
this.busytime,
|
||||
'has correct busytime'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
this.event,
|
||||
subject.event.data,
|
||||
'has correct event'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('#returnTop', function(done) {
|
||||
assert.ok(subject.returnTop);
|
||||
|
||||
subject._returnTo = '/foo';
|
||||
subject._updateUI = function() {
|
||||
assert.equal(subject._returnTo, '/foo');
|
||||
assert.equal(subject._returnTop, '/foo');
|
||||
};
|
||||
|
||||
subject.dispatch({params: {}});
|
||||
|
||||
subject._returnTo = '/bar';
|
||||
subject._updateUI = function() {
|
||||
assert.equal(subject._returnTo, '/bar');
|
||||
assert.equal(subject._returnTop, '/foo');
|
||||
};
|
||||
subject.dispatch({params: {}});
|
||||
|
||||
subject.returnTop();
|
||||
subject._returnTo = '/bar';
|
||||
subject._updateUI = function() {
|
||||
assert.equal(subject._returnTo, '/bar');
|
||||
assert.equal(subject._returnTop, '/bar');
|
||||
done();
|
||||
};
|
||||
subject.dispatch({params: {}});
|
||||
});
|
||||
|
||||
suite('#_createModel', function() {
|
||||
|
||||
test('time is less then now', function() {
|
||||
var model = subject._createModel(new Date(2012, 0, 1));
|
||||
|
||||
assert.hasProperties(
|
||||
model,
|
||||
{
|
||||
startDate: new Date(2012, 0, 1, 8),
|
||||
endDate: new Date(2012, 0, 1, 9)
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('time is today', function() {
|
||||
var now = new Date();
|
||||
var start = new Date(now.getTime());
|
||||
start.setHours(0, 0, 0, 0);
|
||||
// defaults to next hour
|
||||
var realStart = new Date(now.getTime());
|
||||
realStart.setHours(now.getHours() + 1, 0, 0, 0);
|
||||
var end = new Date(now.getTime());
|
||||
end.setHours(now.getHours() + 2, 0, 0, 0);
|
||||
|
||||
var model = subject._createModel(start);
|
||||
|
||||
assert.hasProperties(
|
||||
model,
|
||||
{ startDate: realStart, endDate: end }
|
||||
);
|
||||
});
|
||||
|
||||
test('time is greater then now', function() {
|
||||
var now = new Date();
|
||||
var year = now.getFullYear() + 1;
|
||||
var start = new Date(year, 6, 23);
|
||||
var model = subject._createModel(start);
|
||||
|
||||
assert.hasProperties(
|
||||
model,
|
||||
{
|
||||
startDate: new Date(year, 6, 23, 8),
|
||||
endDate: new Date(year, 6, 23, 9)
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
754
gaia/apps/calendar/test/unit/views/modify_account_test.js
Executable file
754
gaia/apps/calendar/test/unit/views/modify_account_test.js
Executable file
|
|
@ -0,0 +1,754 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var AccountModel = require('models/account');
|
||||
var Factory = require('test/support/factory');
|
||||
var FakePage = require('test/support/fake_page');
|
||||
var ModifyAccount = require('views/modify_account');
|
||||
var OAuthWindow = require('oauth_window');
|
||||
var Presets = require('common/presets');
|
||||
var core = require('core');
|
||||
var nextTick = require('common/next_tick');
|
||||
var router = require('router');
|
||||
|
||||
require('/shared/elements/gaia-header/dist/gaia-header.js');
|
||||
require('dom!modify_event');
|
||||
require('dom!show_event');
|
||||
|
||||
suite('Views.ModifyAccount', function() {
|
||||
var subject;
|
||||
var account;
|
||||
var triggerEvent;
|
||||
var storeFactory;
|
||||
|
||||
var mozApp = {};
|
||||
|
||||
var MockOAuth = function(server, params) {
|
||||
this.server = server;
|
||||
this.params = params;
|
||||
|
||||
this.open = function() {
|
||||
this.isOpen = true;
|
||||
};
|
||||
|
||||
this.close = function() {
|
||||
this.isOpen = false;
|
||||
};
|
||||
};
|
||||
|
||||
var RealOAuth;
|
||||
var realMozApps;
|
||||
function setupOauth() {
|
||||
realMozApps = navigator.mozApps;
|
||||
RealOAuth = OAuthWindow;
|
||||
OAuthWindow = MockOAuth;
|
||||
|
||||
navigator.mozApps = {
|
||||
getSelf: function() {
|
||||
var req = {};
|
||||
nextTick(function() {
|
||||
if (req.onsuccess) {
|
||||
req.onsuccess({
|
||||
target: {
|
||||
result: mozApp
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return req;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function teardownOauth() {
|
||||
OAuthWindow = RealOAuth;
|
||||
navigator.mozApps = realMozApps;
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
});
|
||||
|
||||
function hasClass(value) {
|
||||
return subject.element.classList.contains(value);
|
||||
}
|
||||
|
||||
function getField(name) {
|
||||
return subject.fields[name];
|
||||
}
|
||||
|
||||
function fieldValue(name) {
|
||||
var field = getField(name);
|
||||
return field.value;
|
||||
}
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
// template
|
||||
setup(function() {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="modify-account-view">',
|
||||
'<gaia-header id="modify-account-header" action="back">',
|
||||
'<h1>Account</h1>',
|
||||
'<button class="save">Save</button>',
|
||||
'</gaia-header>',
|
||||
'<button class="save">save</button>',
|
||||
'<button class="cancel">cancel</button>',
|
||||
'<button class="delete-cancel">cancel</button>',
|
||||
'<section role="status">',
|
||||
'<div class="errors"></div>',
|
||||
'</section>',
|
||||
'<form class="modify-account-form">',
|
||||
'<input name="user" />',
|
||||
'<input name="password" />',
|
||||
'<input name="fullUrl" />',
|
||||
'</form>',
|
||||
'<a role="button" class="delete-record">',
|
||||
'<button class="delete-confirm">',
|
||||
'<a class="force-oauth2"></a>',
|
||||
'</div>',
|
||||
'<section id="oauth2">',
|
||||
'<gaia-header id="oauth-header" action="back">',
|
||||
'<h1 class="oauth-browser-title"> </h1>',
|
||||
'</gaia-header>',
|
||||
'<div class="browser-container"></div>',
|
||||
'</section>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
});
|
||||
|
||||
// db
|
||||
setup(function(done) {
|
||||
account = Factory('account', { _id: 1 });
|
||||
|
||||
// assumes account is in a "modify" state
|
||||
subject = new ModifyAccount({
|
||||
model: account
|
||||
});
|
||||
|
||||
storeFactory = core.storeFactory;
|
||||
core.db.open(function() {
|
||||
storeFactory.get('Account').persist(account, done);
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('#authenticationType', function() {
|
||||
assert.equal(subject.authenticationType, 'basic');
|
||||
});
|
||||
|
||||
test('#oauth2Window', function() {
|
||||
assert.ok(subject.oauth2Window);
|
||||
});
|
||||
|
||||
test('#oauth2SignIn', function() {
|
||||
assert.ok(subject.oauth2SignIn);
|
||||
});
|
||||
|
||||
test('#deleteButton', function() {
|
||||
assert.ok(subject.deleteButton);
|
||||
});
|
||||
|
||||
test('#deleteRecordButton', function() {
|
||||
assert.ok(subject.deleteRecordButton);
|
||||
});
|
||||
|
||||
test('#saveButton', function() {
|
||||
assert.ok(subject.saveButton);
|
||||
});
|
||||
|
||||
test('#errors', function() {
|
||||
assert.ok(subject.errors);
|
||||
});
|
||||
|
||||
test('#form', function() {
|
||||
assert.ok(subject.form);
|
||||
});
|
||||
|
||||
suite('#showErrors', function() {
|
||||
var handler;
|
||||
var offline;
|
||||
var sentErr;
|
||||
var show;
|
||||
var showErrorCall;
|
||||
|
||||
setup(function() {
|
||||
handler = core.bridge.createAccount;
|
||||
sentErr = new Error();
|
||||
core.bridge.createAccount = function() {
|
||||
throw sentErr;
|
||||
};
|
||||
show = subject.showErrors;
|
||||
subject.showErrors = function() {
|
||||
showErrorCall = Array.slice(arguments);
|
||||
};
|
||||
offline = subject.isOffline;
|
||||
subject.isOffline = function() {
|
||||
return false;
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.createAccount = handler;
|
||||
subject.isOffline = offline;
|
||||
subject.showErrors = show;
|
||||
});
|
||||
|
||||
test('authorizeError', function() {
|
||||
subject.save(null);
|
||||
|
||||
assert.deepEqual(
|
||||
showErrorCall,
|
||||
[sentErr]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('#fields', function() {
|
||||
var result = subject.fields;
|
||||
|
||||
function hasName(field) {
|
||||
var value = result[field].getAttribute('name');
|
||||
assert.equal(value, field);
|
||||
}
|
||||
|
||||
hasName('user');
|
||||
hasName('password');
|
||||
hasName('fullUrl');
|
||||
});
|
||||
|
||||
suite('#deleteRecord', function() {
|
||||
var model;
|
||||
var show;
|
||||
|
||||
setup(function() {
|
||||
// assign model to simulate
|
||||
// a record that has been dispatched
|
||||
model = Factory('account');
|
||||
model._id = 'myaccount';
|
||||
subject.model = model;
|
||||
show = router.show;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
router.show = show;
|
||||
});
|
||||
|
||||
test('with existing model', function() {
|
||||
var calledShow;
|
||||
var calledRemove;
|
||||
var store = storeFactory.get('Account');
|
||||
|
||||
// we don't really need to redirect
|
||||
// in the test just confirm that it does
|
||||
router.show = function() {
|
||||
calledShow = Array.slice(arguments);
|
||||
};
|
||||
|
||||
// again fake model so we do a fake remove
|
||||
store.remove = function() {
|
||||
calledRemove = Array.slice(arguments);
|
||||
};
|
||||
|
||||
subject.render();
|
||||
triggerEvent(subject.deleteButton, 'click');
|
||||
|
||||
assert.ok(calledRemove, 'called remove');
|
||||
assert.equal(calledRemove[0], model._id, 'removes right id');
|
||||
|
||||
assert.deepEqual(
|
||||
calledShow,
|
||||
['/advanced-settings/']
|
||||
);
|
||||
});
|
||||
|
||||
test('#deleteRecordButton click', function() {
|
||||
this.sinon.stub(subject, 'hideHeaderAndForm');
|
||||
|
||||
subject.render();
|
||||
triggerEvent(subject.deleteRecordButton, 'click');
|
||||
assert.isTrue(subject.hideHeaderAndForm.called);
|
||||
});
|
||||
|
||||
test('#hideHeaderAndForm + #dispatch', function() {
|
||||
assert.isFalse(subject.element.classList.contains(
|
||||
subject.removeDialogClass));
|
||||
subject.hideHeaderAndForm();
|
||||
assert.isTrue(subject.element.classList.contains(
|
||||
subject.removeDialogClass));
|
||||
subject.dispatch({ params: { preset: 'local' } });
|
||||
assert.isFalse(subject.element.classList.contains(
|
||||
subject.removeDialogClass));
|
||||
});
|
||||
|
||||
test('#deleteRecordButton click', function() {
|
||||
this.sinon.stub(subject, 'cancelDelete');
|
||||
|
||||
subject.render();
|
||||
triggerEvent(subject.cancelDeleteButton, 'click');
|
||||
assert.isTrue(subject.cancelDelete.called);
|
||||
});
|
||||
|
||||
test('#cancelDelete', function() {
|
||||
subject.element.classList.add(subject.removeDialogClass);
|
||||
this.sinon.stub(subject, 'cancel');
|
||||
|
||||
subject.cancelDelete();
|
||||
assert.isTrue(subject.cancel.called);
|
||||
assert.isFalse(subject.element.classList.contains(
|
||||
subject.removeDialogClass));
|
||||
});
|
||||
});
|
||||
|
||||
suite('#save', function() {
|
||||
|
||||
var calledWith;
|
||||
var create;
|
||||
var offline;
|
||||
|
||||
setup(function() {
|
||||
calledWith = null;
|
||||
subject.completeUrl = '/settings';
|
||||
FakePage.shown = null;
|
||||
|
||||
create = core.bridge.createAccount;
|
||||
core.bridge.createAccount = function() {
|
||||
calledWith = arguments;
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
offline = subject.isOffline;
|
||||
subject.isOffline = function() {
|
||||
return false;
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.createAccount = create;
|
||||
subject.isOffline = offline;
|
||||
});
|
||||
|
||||
test('clears errors', function() {
|
||||
subject.errors.textContent = 'foo';
|
||||
subject.save();
|
||||
assert.equal(subject.errors.textContent, '', 'clears text');
|
||||
});
|
||||
|
||||
test('with updateModel option', function() {
|
||||
subject.fields.user.value = 'iupdatedu';
|
||||
subject.save({ updateModel: true });
|
||||
assert.equal(subject.model.user, 'iupdatedu');
|
||||
});
|
||||
|
||||
test('on success', function(done) {
|
||||
subject.save().then(() => {
|
||||
done(() => {
|
||||
assert.equal(calledWith[0], subject.model, 'model');
|
||||
|
||||
assert.equal(
|
||||
FakePage.shown,
|
||||
subject.completeUrl,
|
||||
'redirects to complete url'
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
hasClass(subject.progressClass),
|
||||
'disabled progress class'
|
||||
);
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
suite('on failure', function() {
|
||||
setup(function() {
|
||||
core.bridge.createAccount = function() {
|
||||
calledWith = arguments;
|
||||
return Promise.reject();
|
||||
};
|
||||
});
|
||||
|
||||
test('failure', function(done) {
|
||||
subject.save().catch(() => {
|
||||
done(() => {
|
||||
assert.ok(calledWith, 'sends request');
|
||||
assert.equal(calledWith[0], subject.model);
|
||||
|
||||
assert.ok(
|
||||
!hasClass(subject.progressClass),
|
||||
'hides progress'
|
||||
);
|
||||
|
||||
assert.notEqual(
|
||||
FakePage.shown,
|
||||
subject.completeUrl,
|
||||
'does not redirect on complete'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('#_createModel', function() {
|
||||
var preset = 'local';
|
||||
|
||||
subject.model = null;
|
||||
|
||||
var model = subject._createModel(preset);
|
||||
|
||||
assert.instanceOf(model, AccountModel);
|
||||
|
||||
assert.equal(
|
||||
model.providerType,
|
||||
Presets.local.providerType
|
||||
);
|
||||
});
|
||||
|
||||
test('#updateForm', function() {
|
||||
account.user = 'james';
|
||||
//we never display the password.
|
||||
account.password = 'baz';
|
||||
account.fullUrl = 'http://google.com/path/';
|
||||
|
||||
subject.updateForm();
|
||||
|
||||
assert.equal(fieldValue('user'), 'james');
|
||||
assert.equal(fieldValue('password'), '');
|
||||
assert.equal(fieldValue('fullUrl'), 'http://google.com/path/');
|
||||
});
|
||||
|
||||
test('#updateModel', function() {
|
||||
var fields = subject.fields;
|
||||
fields.user.value = 'user';
|
||||
fields.password.value = 'pass';
|
||||
fields.fullUrl.value = 'http://google.com/foo/';
|
||||
|
||||
subject.updateModel();
|
||||
|
||||
assert.equal(account.user, 'user');
|
||||
assert.equal(account.password, 'pass');
|
||||
assert.equal(account.fullUrl, 'http://google.com/foo/');
|
||||
});
|
||||
|
||||
suite('#dispatch', function() {
|
||||
|
||||
test('new', function(done) {
|
||||
subject.dispatch({
|
||||
params: { preset: 'local' }
|
||||
}).then(() => {
|
||||
done(function() {
|
||||
assert.instanceOf(
|
||||
subject.model,
|
||||
AccountModel,
|
||||
'creates model'
|
||||
);
|
||||
|
||||
assert.hasProperties(
|
||||
subject.model,
|
||||
Presets.local.options,
|
||||
'uses preset options'
|
||||
);
|
||||
|
||||
assert.equal(subject.preset, Presets.local);
|
||||
assert.equal(subject.completeUrl, '/settings/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('existing', function(done) {
|
||||
var destroyed;
|
||||
|
||||
subject.model = {};
|
||||
subject.destroy = function() {
|
||||
destroyed = true;
|
||||
};
|
||||
|
||||
subject.dispatch({
|
||||
// send as string to emulate real conditions
|
||||
params: { id: String(account._id) }
|
||||
}).then(() => {
|
||||
done(function() {
|
||||
assert.ok(destroyed, 'should destroy previous state');
|
||||
assert.equal(subject.completeUrl, '/settings/');
|
||||
|
||||
assert.hasProperties(
|
||||
account,
|
||||
subject.model,
|
||||
'loads account'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('#render', function() {
|
||||
suite('with error', function() {
|
||||
setup(function() {
|
||||
account.error = {};
|
||||
subject.render();
|
||||
});
|
||||
|
||||
test('has .error class', function() {
|
||||
assert.isTrue(hasClass('error'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('normal flow', function() {
|
||||
|
||||
var create;
|
||||
|
||||
setup(function() {
|
||||
create = core.bridge.createAccount;
|
||||
account.user = 'foo';
|
||||
subject.fields.password.value = 'foo';
|
||||
subject.render();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.createAccount = create;
|
||||
});
|
||||
|
||||
|
||||
test('save button', function(done) {
|
||||
subject.fields.user.value = 'updated';
|
||||
|
||||
core.bridge.createAccount = function(model) {
|
||||
done(function() {
|
||||
assert.equal(
|
||||
model.user,
|
||||
subject.fields.user.value,
|
||||
'updates fields'
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
triggerEvent(subject.saveButton, 'click');
|
||||
});
|
||||
|
||||
test('type', function(done) {
|
||||
assert.ok(subject.type);
|
||||
done();
|
||||
});
|
||||
|
||||
test('update', function(done) {
|
||||
assert.equal(subject.fields.user.value, 'foo');
|
||||
done();
|
||||
});
|
||||
|
||||
test('clear password', function() {
|
||||
assert.equal(subject.fields.password.value, '');
|
||||
});
|
||||
|
||||
test('type class', function() {
|
||||
assert.isFalse(hasClass('error'));
|
||||
assert.isTrue(hasClass(subject.type));
|
||||
assert.isTrue(hasClass('preset-' + account.preset));
|
||||
assert.isTrue(hasClass('provider-' + account.providerType));
|
||||
assert.isTrue(hasClass('auth-' + subject.authenticationType));
|
||||
});
|
||||
});
|
||||
|
||||
suite('oauth flow', function() {
|
||||
var callsSave;
|
||||
|
||||
suiteSetup(setupOauth);
|
||||
suiteTeardown(teardownOauth);
|
||||
|
||||
var clearsCookies;
|
||||
mozApp = {
|
||||
clearBrowserData: function() {
|
||||
var req = {};
|
||||
|
||||
nextTick(function() {
|
||||
clearsCookies = true;
|
||||
req.onsuccess && req.onsuccess();
|
||||
});
|
||||
return req;
|
||||
}
|
||||
};
|
||||
|
||||
setup(function(done) {
|
||||
clearsCookies = false;
|
||||
subject.save = function() {
|
||||
callsSave = true;
|
||||
};
|
||||
|
||||
// Oauth flows are only for new accounts
|
||||
subject.model = {};
|
||||
|
||||
subject.preset = Presets.google;
|
||||
subject.render();
|
||||
|
||||
var realFlow = subject._redirectToOAuthFlow;
|
||||
subject._redirectToOAuthFlow = function() {
|
||||
realFlow.apply(this, arguments);
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('clears cookies', function() {
|
||||
assert.ok(clearsCookies, 'cookies where cleared');
|
||||
});
|
||||
|
||||
test('authenticationType', function() {
|
||||
assert.equal(
|
||||
subject.authenticationType,
|
||||
subject.preset.authenticationType,
|
||||
'sets authentication type to preset'
|
||||
);
|
||||
});
|
||||
|
||||
test('class names', function() {
|
||||
assert.isTrue(hasClass('auth-' + subject.authenticationType));
|
||||
});
|
||||
|
||||
test('oauth dialog comples with error', function(done) {
|
||||
subject.cancel = done;
|
||||
assert.ok(subject._oauthDialog, 'has dialog');
|
||||
subject._oauthDialog.oncomplete({ error: 'access_denied' });
|
||||
});
|
||||
|
||||
test('oauth flow is a success', function() {
|
||||
var code = 'xxx';
|
||||
assert.ok(subject._oauthDialog, 'has dialog');
|
||||
subject._oauthDialog.oncomplete({ code: code });
|
||||
assert.equal(subject.model.oauth.code, code, 'sets code');
|
||||
assert.ok(callsSave);
|
||||
});
|
||||
});
|
||||
|
||||
suite('modify oauth account', function() {
|
||||
|
||||
suiteSetup(setupOauth);
|
||||
suiteTeardown(teardownOauth);
|
||||
|
||||
setup(function() {
|
||||
subject.preset = Presets.google;
|
||||
subject.render();
|
||||
});
|
||||
|
||||
test('oauth flow is not triggered', function() {
|
||||
assert.equal(subject._oauthDialog, undefined, 'does not have dialog');
|
||||
assert.ok(subject.fields.user.disabled);
|
||||
});
|
||||
|
||||
test('force sign in', function() {
|
||||
// stub out real oauth flow window to prevent failures
|
||||
subject._redirectToOAuthFlow = function() {};
|
||||
|
||||
assert.ok(
|
||||
!subject.oauth2Window.classList.contains('active'),
|
||||
'is inactive before click'
|
||||
);
|
||||
|
||||
triggerEvent(subject.oauth2SignIn, 'click');
|
||||
|
||||
assert.ok(
|
||||
subject.oauth2Window.classList.contains('active'), 'shows oauth2'
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('#destroy', function() {
|
||||
suite('normal flow', function() {
|
||||
setup(function() {
|
||||
subject.model.error = {};
|
||||
subject.render();
|
||||
subject.destroy();
|
||||
});
|
||||
|
||||
test('save button', function() {
|
||||
var called;
|
||||
|
||||
subject._persistForm = function() {
|
||||
called = true;
|
||||
};
|
||||
|
||||
triggerEvent(subject.saveButton, 'click');
|
||||
assert.ok(!called);
|
||||
});
|
||||
|
||||
test('fields', function() {
|
||||
assert.equal(subject._fields, null);
|
||||
assert.equal(subject.fields.user.disabled, false,
|
||||
're-enable username field');
|
||||
});
|
||||
|
||||
test('type class', function() {
|
||||
assert.isFalse(hasClass(subject.type));
|
||||
assert.isFalse(hasClass('error'));
|
||||
assert.isFalse(hasClass('preset-' + account.preset));
|
||||
assert.isFalse(hasClass('provider-' + account.providerType));
|
||||
});
|
||||
});
|
||||
|
||||
suite('oauth2 edit flow', function() {
|
||||
setup(function() {
|
||||
subject.preset = Presets.google;
|
||||
subject.model._id = 1;
|
||||
|
||||
assert.equal(subject.authenticationType, 'oauth2');
|
||||
subject.render();
|
||||
subject.destroy();
|
||||
});
|
||||
|
||||
test('should disable force display of oauth2', function() {
|
||||
triggerEvent(subject.oauth2SignIn, 'click');
|
||||
assert.ok(
|
||||
!subject.oauth2Window.classList.contains('active'),
|
||||
'is ignored after destroy'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('submit form', function() {
|
||||
var create;
|
||||
|
||||
setup(function() {
|
||||
create = core.bridge.createAccount;
|
||||
account.user = 'foo';
|
||||
subject.fields.password.value = 'foo';
|
||||
subject.render();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.createAccount = create;
|
||||
});
|
||||
|
||||
test('default is prevented', function(done) {
|
||||
subject.element.addEventListener('submit', function(e) {
|
||||
assert.ok(e.defaultPrevented);
|
||||
done();
|
||||
});
|
||||
|
||||
core.bridge.createAccount = function(model) {};
|
||||
|
||||
triggerEvent(subject.form, 'submit');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
1204
gaia/apps/calendar/test/unit/views/modify_event_test.js
Executable file
1204
gaia/apps/calendar/test/unit/views/modify_event_test.js
Executable file
File diff suppressed because it is too large
Load diff
262
gaia/apps/calendar/test/unit/views/month_day_agenda_test.js
Executable file
262
gaia/apps/calendar/test/unit/views/month_day_agenda_test.js
Executable file
|
|
@ -0,0 +1,262 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var MonthDayAgenda = require('views/month_day_agenda');
|
||||
var core = require('core');
|
||||
var template = require('templates/month_day_agenda');
|
||||
var intl = require('intl');
|
||||
|
||||
|
||||
suite('Views.MonthDayAgenda', function() {
|
||||
var subject;
|
||||
|
||||
suiteSetup(function() {
|
||||
intl.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
core.db.close();
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="month-day-agenda">',
|
||||
'<div id="event-list-date"></div>',
|
||||
'<div id="empty-message"></div>',
|
||||
'<div class="day-events"></div>',
|
||||
'</div>'
|
||||
].join(' ');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
subject = new MonthDayAgenda();
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
suite('#changeDate', function() {
|
||||
var currentDate;
|
||||
|
||||
setup(function() {
|
||||
currentDate = document.getElementById('event-list-date');
|
||||
sinon.spy(core.bridge, 'observeDay');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.observeDay.restore();
|
||||
});
|
||||
|
||||
test('> date', function() {
|
||||
var now = new Date();
|
||||
var format = 'months-day-view-header-format';
|
||||
subject.changeDate(now);
|
||||
|
||||
assert.equal(
|
||||
currentDate.getAttribute('data-l10n-date-format'),
|
||||
format,
|
||||
'should set the currentDate textContent');
|
||||
|
||||
assert.equal(currentDate.dataset.date, now.toString());
|
||||
assert.deepEqual(currentDate.dataset.l10nDateFormat, format);
|
||||
|
||||
assert.ok(
|
||||
core.bridge.observeDay.calledWith(now),
|
||||
'should listen current day'
|
||||
);
|
||||
});
|
||||
|
||||
test('> null', function() {
|
||||
var format = 'months-day-view-header-format';
|
||||
var oldDate = new Date(2012, 8, 1);
|
||||
subject.date = oldDate;
|
||||
var oldObserver = { cancel: sinon.spy() };
|
||||
subject._observer = oldObserver;
|
||||
subject.changeDate(null);
|
||||
|
||||
assert.notDeepEqual(subject.date, oldDate, 'date changed');
|
||||
|
||||
assert.equal(
|
||||
currentDate.getAttribute('data-l10n-date-format'),
|
||||
format,
|
||||
'should set the currentDate textContent');
|
||||
|
||||
assert.deepEqual(
|
||||
new Date(currentDate.dataset.date),
|
||||
new Date(subject.date)
|
||||
);
|
||||
assert.deepEqual(currentDate.dataset.l10nDateFormat, format);
|
||||
|
||||
assert.ok(
|
||||
oldObserver.cancel.called,
|
||||
'should remove previous listener'
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
core.bridge.observeDay.calledWith(subject.date),
|
||||
'should listen current day'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_render', function() {
|
||||
var events = document.createElement('div');
|
||||
var emptyMessage = {};
|
||||
|
||||
setup(function() {
|
||||
sinon.stub(subject, '_findElement')
|
||||
.withArgs('events').returns(events)
|
||||
.withArgs('emptyMessage').returns(emptyMessage);
|
||||
|
||||
subject.date = new Date(2014, 9, 22);
|
||||
emptyMessage.classList = {
|
||||
toggle: sinon.spy()
|
||||
};
|
||||
|
||||
sinon.spy(template.event, 'render');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject._findElement.restore();
|
||||
template.event.render.restore();
|
||||
});
|
||||
|
||||
test('> no record', function() {
|
||||
subject._render({ basic: [], allday: [], amount: 0 });
|
||||
|
||||
assert.deepEqual(subject.events.innerHTML, '', 'should clear events');
|
||||
|
||||
assert.ok(
|
||||
emptyMessage.classList.toggle.calledWith('active', true),
|
||||
'should display empty message'
|
||||
);
|
||||
});
|
||||
|
||||
test('> with records', function() {
|
||||
subject._render({
|
||||
amount: 2,
|
||||
basic: [
|
||||
{
|
||||
event: {
|
||||
calendarId: '3',
|
||||
remote: {
|
||||
title: 'Lorem',
|
||||
location: 'Ipsum',
|
||||
alarms: []
|
||||
}
|
||||
},
|
||||
busytime: {
|
||||
_id: '3-lorem',
|
||||
startDate: new Date(2014, 9, 22, 1),
|
||||
endDate: new Date(2014, 9, 22, 3)
|
||||
},
|
||||
color: '#BADA55'
|
||||
},
|
||||
{
|
||||
event: {
|
||||
calendarId: '7',
|
||||
remote: {
|
||||
title: 'Foo',
|
||||
location: 'Bar',
|
||||
alarms: [1, 2]
|
||||
}
|
||||
},
|
||||
busytime: {
|
||||
_id: '7-busy-foo',
|
||||
startDate: new Date(2014, 9, 22, 13),
|
||||
endDate: new Date(2014, 9, 22, 14)
|
||||
},
|
||||
color: '#00FFCC'
|
||||
}
|
||||
],
|
||||
allday: []
|
||||
});
|
||||
|
||||
// should pass proper arguments to template
|
||||
// output is already tested by template unit test
|
||||
sinon.assert.calledWithMatch(template.event.render, {
|
||||
hasAlarms: true,
|
||||
busytimeId: '7-busy-foo',
|
||||
color: '#00FFCC',
|
||||
title: 'Foo',
|
||||
location: 'Bar',
|
||||
startTime: new Date(2014, 9, 22, 13),
|
||||
endTime: new Date(2014, 9, 22, 14),
|
||||
isAllDay: false
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('#handleEvent', function() {
|
||||
|
||||
/*
|
||||
// This test is currently failing and has been temporarily disabled as per
|
||||
// Bug 838993. It should be fixed and re-enabled as soon as possible as per
|
||||
// Bug 840489.
|
||||
// This test appears to make incorrect assumptions about localization details
|
||||
// (it does not fail on systems configured for US English).
|
||||
test('selectedDayChange', function() {
|
||||
var date = new Date(2012, 1, 1);
|
||||
var calledWith;
|
||||
|
||||
// start with different date...
|
||||
subject.date = new Date(2012, 1, 27);
|
||||
|
||||
// initialize events
|
||||
subject.render();
|
||||
|
||||
subject.changeDate = function() {
|
||||
Calendar.Views.MonthsDay.prototype.changeDate.apply(
|
||||
this, arguments
|
||||
);
|
||||
|
||||
calledWith = arguments;
|
||||
};
|
||||
|
||||
subject.controller.selectedDay = date;
|
||||
assert.equal(
|
||||
calledWith[0],
|
||||
date,
|
||||
'should change date in view when controller changes'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
subject.date,
|
||||
date
|
||||
);
|
||||
|
||||
var html = subject.header.outerHTML;
|
||||
assert.ok(html);
|
||||
assert.include(html, date.toLocaleFormat('%A'));
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
/*
|
||||
// This test is currently failing and has been temporarily disabled as per
|
||||
// Bug 838993. It should be fixed and re-enabled as soon as possible as per
|
||||
// Bug 840489.
|
||||
// This test appears to make incorrect assumptions about localization details
|
||||
// (it does not fail on systems configured for US English).
|
||||
test('#render', function() {
|
||||
var date = new Date();
|
||||
var span = Calendar.Calc.spanOfDay(date);
|
||||
|
||||
|
||||
subject.render();
|
||||
assert.deepEqual(subject.timespan, span);
|
||||
|
||||
assert.ok(subject.allDayElement, 'has all day');
|
||||
assert.ok(subject.events, 'has events');
|
||||
|
||||
var html = subject.header.outerHTML;
|
||||
assert.ok(html);
|
||||
assert.include(html, date.toLocaleFormat('%A'));
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
});
|
||||
104
gaia/apps/calendar/test/unit/views/month_day_test.js
Executable file
104
gaia/apps/calendar/test/unit/views/month_day_test.js
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var MonthDay = require('views/month_day');
|
||||
|
||||
suite('Views.MonthDay', function() {
|
||||
var container;
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
container = document.createElement('div');
|
||||
subject = new MonthDay({
|
||||
container: container,
|
||||
date: new Date(2014, 6, 23),
|
||||
month: new Date(2014, 6, 1)
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.destroy();
|
||||
container.innerHTML = '';
|
||||
});
|
||||
|
||||
suite('#create', function() {
|
||||
test('same month', function() {
|
||||
subject.create();
|
||||
var id = 'month-view-day-d-2014-6-23';
|
||||
|
||||
var li = subject.element;
|
||||
assert.equal(li.getAttribute('role'), 'gridcell');
|
||||
assert.equal(li.tabindex, '0');
|
||||
assert.equal(
|
||||
li.getAttribute('aria-describedby'),
|
||||
`${id}-busy-indicator ${id}-description`
|
||||
);
|
||||
assert.equal(li.dataset.date, 'd-2014-6-23');
|
||||
|
||||
var day = li.querySelector('.day');
|
||||
assert.equal(day.getAttribute('role'), 'button');
|
||||
assert.equal(day.textContent.trim(), '23');
|
||||
|
||||
var busy = li.querySelector('.busy-indicator');
|
||||
assert.equal(busy.id, `${id}-busy-indicator`);
|
||||
assert.equal(busy.getAttribute('aria-hidden'), 'true');
|
||||
|
||||
var description = li.querySelector(`#${id}-description`);
|
||||
assert.equal(description.getAttribute('aria-hidden'), 'true');
|
||||
assert.equal(description.getAttribute('data-l10n-id'), '');
|
||||
});
|
||||
|
||||
test('past-other-month', function() {
|
||||
subject.date = new Date(2014, 5, 30);
|
||||
subject.create();
|
||||
assert.include(
|
||||
subject.element.outerHTML,
|
||||
'data-l10n-id="past-other-month-description"'
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
// Test disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1179085
|
||||
test('future-other-month', function() {
|
||||
var future = new Date();
|
||||
future.setFullYear(future.getFullYear() + 1);
|
||||
subject.date = future;
|
||||
subject.create();
|
||||
assert.include(
|
||||
subject.element.outerHTML,
|
||||
'data-l10n-id="future-other-month-description"'
|
||||
);
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
suite('#_updateBusyCount', function() {
|
||||
var busy;
|
||||
|
||||
setup(function() {
|
||||
subject.create();
|
||||
busy = subject.element.querySelector('.busy-indicator');
|
||||
});
|
||||
|
||||
test('add', function() {
|
||||
subject._updateBusyCount({ amount: 2 });
|
||||
assert.lengthOf(busy.childNodes, 2);
|
||||
subject._updateBusyCount({ amount: 5 });
|
||||
assert.lengthOf(busy.childNodes, 3);
|
||||
});
|
||||
|
||||
test('remove', function() {
|
||||
subject._updateBusyCount({ amount: 5 });
|
||||
assert.lengthOf(busy.childNodes, 3);
|
||||
subject._updateBusyCount({ amount: 3 });
|
||||
assert.lengthOf(busy.childNodes, 3);
|
||||
subject._updateBusyCount({ amount: 2 });
|
||||
assert.lengthOf(busy.childNodes, 2);
|
||||
subject._updateBusyCount({ amount: 0 });
|
||||
assert.lengthOf(busy.childNodes, 0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
209
gaia/apps/calendar/test/unit/views/month_test.js
Executable file
209
gaia/apps/calendar/test/unit/views/month_test.js
Executable file
|
|
@ -0,0 +1,209 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var Calc = require('common/calc');
|
||||
var Month = require('views/month');
|
||||
var core = require('core');
|
||||
|
||||
requireCommon('test/synthetic_gestures.js');
|
||||
|
||||
suite('Views.Month', function() {
|
||||
var subject,
|
||||
controller,
|
||||
triggerEvent;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
core.db.close();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="current-month-year">',
|
||||
'</div>',
|
||||
'<div id="month-view">',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
controller = core.timeController;
|
||||
controller.move(new Date());
|
||||
|
||||
subject = new Month();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.destroy();
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.equal(subject.element, document.querySelector('#month-view'));
|
||||
});
|
||||
|
||||
suite('events', function() {
|
||||
|
||||
setup(function() {
|
||||
subject._initEvents();
|
||||
});
|
||||
|
||||
test('dom: click', function() {
|
||||
subject.onfirstseen();
|
||||
|
||||
var el = subject.element.querySelector('.month-day');
|
||||
var date = Calc.dateFromId(el.dataset.date);
|
||||
|
||||
triggerEvent(el, 'click');
|
||||
assert.deepEqual(
|
||||
controller.selectedDay, date,
|
||||
'tapping element should change selected date'
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
// These tests are currently failing and have been temporarily disabled as per
|
||||
// Bug 838993. They should be fixed and re-enabled as soon as possible as per
|
||||
// Bug 840489.
|
||||
test('dom: dbltap', function() {
|
||||
var calledWith;
|
||||
core.router.show = function(url) {
|
||||
calledWith = url;
|
||||
};
|
||||
|
||||
subject.render();
|
||||
|
||||
// find something with [data-date];
|
||||
var el = subject.element.querySelector(
|
||||
'[data-date]'
|
||||
);
|
||||
|
||||
triggerEvent(el, 'dbltap');
|
||||
|
||||
assert.equal(
|
||||
calledWith,
|
||||
'/day/',
|
||||
'double tapping on date should activate day view'
|
||||
);
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
test('controller: monthChange', function() {
|
||||
var calledActivateTime = null;
|
||||
|
||||
subject.changeDate = function(month) {
|
||||
calledActivateTime = month;
|
||||
};
|
||||
|
||||
var date = new Date(2012, 1, 1);
|
||||
controller.move(date);
|
||||
|
||||
assert.deepEqual(calledActivateTime, date);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('#_onswipe', function() {
|
||||
var date = new Date(2012, 4, 1);
|
||||
var expected = new Date(2012, 3, 1);
|
||||
subject.date = date;
|
||||
|
||||
subject._onswipe({
|
||||
dy: 0,
|
||||
dx: window.innerWidth / 5,
|
||||
direction: 'right'
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
core.timeController.selectedDay,
|
||||
expected,
|
||||
'selects first day of previous month'
|
||||
);
|
||||
});
|
||||
|
||||
test('#_onwheel', function() {
|
||||
var date = new Date(2012, 4, 10);
|
||||
var expected = new Date(2012, 5, 1);
|
||||
subject.date = date;
|
||||
|
||||
subject._onwheel({
|
||||
deltaMode: window.WheelEvent.DOM_DELTA_PAGE,
|
||||
DOM_DELTA_PAGE: window.WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: 1,
|
||||
deltaY: 0
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
core.timeController.selectedDay,
|
||||
expected,
|
||||
'selects first day of month'
|
||||
);
|
||||
});
|
||||
|
||||
test('#_nextTime', function() {
|
||||
subject.date = new Date(2012, 4, 1);
|
||||
assert.deepEqual(
|
||||
subject._nextTime(),
|
||||
new Date(2012, 5, 1)
|
||||
);
|
||||
});
|
||||
|
||||
test('#_previousTime', function() {
|
||||
subject.date = new Date(2012, 5, 1);
|
||||
assert.deepEqual(
|
||||
subject._previousTime(),
|
||||
new Date(2012, 4, 1)
|
||||
);
|
||||
});
|
||||
|
||||
test('#changeDate', function() {
|
||||
var base;
|
||||
|
||||
function dayIds() {
|
||||
var months = subject.element.querySelectorAll('section.month');
|
||||
return Array.map(months, el => el.dataset.date).join(', ');
|
||||
}
|
||||
|
||||
base = new Date(2014, 10, 11);
|
||||
subject.changeDate(base);
|
||||
assert.ok(subject.currentFrame.active, 'currentFrame.active');
|
||||
assert.deepEqual(
|
||||
subject.currentFrame.date,
|
||||
new Date(2014, 10, 1),
|
||||
'base date should always be first day of the month'
|
||||
);
|
||||
assert.equal(
|
||||
dayIds(),
|
||||
'd-2014-10-1',
|
||||
'1: single element at first call'
|
||||
);
|
||||
|
||||
base = new Date(2015, 0, 1);
|
||||
subject.changeDate(base);
|
||||
assert.deepEqual(subject.currentFrame.date, base, '2: currentFrame.date');
|
||||
assert.equal(
|
||||
dayIds(),
|
||||
'd-2014-10-1, d-2015-0-1',
|
||||
'2: month elements should be sorted'
|
||||
);
|
||||
|
||||
base = new Date(2014, 3, 1);
|
||||
subject.changeDate(base);
|
||||
assert.deepEqual(subject.currentFrame.date, base, '3: currentFrame.date');
|
||||
assert.equal(
|
||||
dayIds(),
|
||||
'd-2014-3-1, d-2014-10-1, d-2015-0-1',
|
||||
'3: month elements should be sorted'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
126
gaia/apps/calendar/test/unit/views/multi_day_test.js
Executable file
126
gaia/apps/calendar/test/unit/views/multi_day_test.js
Executable file
|
|
@ -0,0 +1,126 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var MultiDay = require('views/multi_day');
|
||||
var core = require('core');
|
||||
|
||||
suite('Views.MultiDay', function() {
|
||||
var subject;
|
||||
var timeController;
|
||||
|
||||
setup(function() {
|
||||
subject = new MultiDay();
|
||||
subject.element = document.createElement('div');
|
||||
subject.element.innerHTML = '<div class="md__sidebar"></div>';
|
||||
subject._currentTime = {
|
||||
refresh: this.sinon.spy()
|
||||
};
|
||||
timeController = core.timeController;
|
||||
});
|
||||
|
||||
suite('#onactive', function() {
|
||||
var stubOnFirstSeen;
|
||||
var stubRender;
|
||||
var stubResetScroll;
|
||||
var stubScrollToHour;
|
||||
|
||||
setup(function() {
|
||||
stubOnFirstSeen = sinon.stub(subject, 'onfirstseen');
|
||||
stubRender = sinon.stub(subject, '_render');
|
||||
stubResetScroll = sinon.stub(subject, '_resetScroll');
|
||||
stubScrollToHour = sinon.stub(subject, '_scrollToHour');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubOnFirstSeen.restore();
|
||||
stubRender.restore();
|
||||
stubResetScroll.restore();
|
||||
stubScrollToHour.restore();
|
||||
});
|
||||
|
||||
test('First time active', function() {
|
||||
subject.onactive();
|
||||
sinon.assert.calledOnce(stubOnFirstSeen);
|
||||
sinon.assert.calledOnce(stubRender);
|
||||
sinon.assert.calledOnce(stubResetScroll);
|
||||
sinon.assert.calledOnce(stubScrollToHour);
|
||||
});
|
||||
|
||||
test('Do not scroll when come back from other screen', function() {
|
||||
subject.baseDate = timeController.position;
|
||||
subject.seen = true;
|
||||
subject.onactive();
|
||||
assert.isFalse(stubOnFirstSeen.called);
|
||||
assert.isFalse(stubResetScroll.called);
|
||||
assert.isFalse(stubScrollToHour.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('localized and timeformatchange', function() {
|
||||
var sidebar;
|
||||
|
||||
setup(function() {
|
||||
navigator.mozHour12 = false;
|
||||
sidebar = subject.sidebar;
|
||||
subject._visibleRange = 123;
|
||||
});
|
||||
|
||||
function assertTimeRefresh() {
|
||||
// make sure we rebuild all hours during localize
|
||||
var i = -1, date = new Date(0), hour;
|
||||
while (++i < 24) {
|
||||
date.setHours(i, 0, 0, 0);
|
||||
hour = sidebar.querySelector('.md__hour-' + i);
|
||||
assert.equal(hour.textContent, i, 'display hour');
|
||||
assert.equal(
|
||||
hour.querySelector('.md__display-hour').dataset.date,
|
||||
date,
|
||||
'date data'
|
||||
);
|
||||
}
|
||||
|
||||
// make sure we update the current time
|
||||
assert.ok(
|
||||
subject._currentTime.refresh.calledOnce,
|
||||
'called refresh'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
subject._currentTime.timespan,
|
||||
subject._visibleRange,
|
||||
'current time timespan matches the _visibleRange'
|
||||
);
|
||||
}
|
||||
|
||||
test('localized', function() {
|
||||
subject.handleEvent({type: 'localized'});
|
||||
assertTimeRefresh();
|
||||
});
|
||||
|
||||
test('timeformatchange', function() {
|
||||
subject.handleEvent({type: 'timeformatchange'});
|
||||
assertTimeRefresh();
|
||||
});
|
||||
});
|
||||
|
||||
test('#_updateBaseDateAfterScroll', function() {
|
||||
// we need to make sure it's updating the timeController position and
|
||||
// selectedDay after the drag so moving to day/month views have the
|
||||
// expected output (highlight first day of the week view)
|
||||
subject.baseDate = new Date(2014, 6, 23);
|
||||
subject._updateBaseDateAfterScroll(-3);
|
||||
var expected = (new Date(2014, 6, 20)).toISOString();
|
||||
assert.equal(
|
||||
timeController.position.toISOString(),
|
||||
expected,
|
||||
'position'
|
||||
);
|
||||
assert.equal(
|
||||
timeController.selectedDay.toISOString(),
|
||||
expected,
|
||||
'selectedDay'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
515
gaia/apps/calendar/test/unit/views/settings_test.js
Executable file
515
gaia/apps/calendar/test/unit/views/settings_test.js
Executable file
|
|
@ -0,0 +1,515 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var CalendarTemplate = require('templates/calendar');
|
||||
var Factory = require('test/support/factory');
|
||||
var Settings = require('views/settings');
|
||||
var View = require('view');
|
||||
var core = require('core');
|
||||
var nextTick = require('common/next_tick');
|
||||
var suiteGroup = require('test/support/suite_group');
|
||||
var waitFor = require('test/support/wait_for');
|
||||
|
||||
requireCommon('test/synthetic_gestures.js');
|
||||
|
||||
suiteGroup('views/settings', function() {
|
||||
/* jshint -W027 */
|
||||
return;
|
||||
var subject;
|
||||
var store;
|
||||
var controller;
|
||||
var storeFactory;
|
||||
var syncController;
|
||||
var template;
|
||||
var triggerEvent;
|
||||
var account;
|
||||
var models;
|
||||
|
||||
function stageModels(list) {
|
||||
var object = Object.create(null);
|
||||
|
||||
setup(function(done) {
|
||||
account = Factory('account', { _id: 'testacc' });
|
||||
|
||||
var trans = core.db.transaction(
|
||||
['calendars', 'accounts'], 'readwrite'
|
||||
);
|
||||
|
||||
trans.oncomplete = function() {
|
||||
done();
|
||||
};
|
||||
|
||||
trans.onerror = function(e) {
|
||||
done(e.target.error);
|
||||
};
|
||||
|
||||
storeFactory.get('Account').persist(account, trans);
|
||||
|
||||
var model;
|
||||
for (var key in list) {
|
||||
list[key].accountId = account._id;
|
||||
model = Factory('calendar', list[key]);
|
||||
store.persist((object[key] = model), trans);
|
||||
}
|
||||
});
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
syncController = core.syncController;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="settings">',
|
||||
' <header>',
|
||||
' <button data-l10n-id="back"',
|
||||
' class="settings-back"></button>',
|
||||
' </header>',
|
||||
' <div class="settings-shield"></div>',
|
||||
' <div class="settings-drawer-container">',
|
||||
' <div class="settings-drawer">',
|
||||
' <ol class="calendars">',
|
||||
' </ol>',
|
||||
' <ul role="tablist" class="bb-tablist" dir="ltr">',
|
||||
' <li class="settings">',
|
||||
' <span class="icon"',
|
||||
' data-l10n-id="advanced-settings-short-icon-button">',
|
||||
' </span>',
|
||||
' </li>',
|
||||
' <li class="sync update">',
|
||||
' <span class="icon"',
|
||||
' data-l10n-id="drawer-sync-icon-button"></span>',
|
||||
' <span class="sync-progress" role="progressbar"></span>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
controller = core.timeController;
|
||||
storeFactory = core.storeFactory;
|
||||
store = storeFactory.get('Calendar');
|
||||
template = CalendarTemplate;
|
||||
|
||||
subject = new Settings({
|
||||
syncProgressTarget: div,
|
||||
// normally this is higher in production but
|
||||
// we don't need to wait that long in tests.
|
||||
waitBeforePersist: 10
|
||||
});
|
||||
|
||||
subject.calendarList = {
|
||||
first: {
|
||||
localDisplayed: true,
|
||||
_id: 'first',
|
||||
remote: {
|
||||
name: 'first'
|
||||
}
|
||||
},
|
||||
local: {
|
||||
localDisplayed: true,
|
||||
_id: 'local-first',
|
||||
remote: {
|
||||
name: 'this should not be used!!!!'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
core.db.open(done);
|
||||
|
||||
models = stageModels({
|
||||
displayed: {
|
||||
localDisplayed: true,
|
||||
_id: 1
|
||||
},
|
||||
|
||||
hidden: {
|
||||
localDisplayed: false,
|
||||
_id: 'hidden'
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts', 'calendars'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.instanceOf(subject, View);
|
||||
assert.equal(
|
||||
subject.element, document.querySelector('#settings')
|
||||
);
|
||||
});
|
||||
|
||||
test('#calendars', function() {
|
||||
assert.ok(subject.calendars);
|
||||
});
|
||||
|
||||
test('#syncButton', function() {
|
||||
assert.ok(subject.syncButton);
|
||||
});
|
||||
|
||||
test('#syncProgressTarget', function() {
|
||||
assert.ok(subject.syncProgressTarget);
|
||||
});
|
||||
|
||||
test('#syncProgress', function() {
|
||||
assert.ok(subject.syncProgress);
|
||||
});
|
||||
|
||||
suite('#_observeAccountStore', function() {
|
||||
var accounts = testSupport.calendar.dbFixtures(
|
||||
'account',
|
||||
'Account',
|
||||
{
|
||||
sync: { _id: 'sync', providerType: 'Caldav' },
|
||||
nosync: { _id: 'nosync', providerType: 'Local' }
|
||||
}
|
||||
);
|
||||
|
||||
var syncAccount;
|
||||
var accountStore;
|
||||
setup(function(done) {
|
||||
accountStore = storeFactory.get('Account');
|
||||
syncAccount = accounts.sync;
|
||||
|
||||
subject.render();
|
||||
subject.onrender = done;
|
||||
});
|
||||
|
||||
suite('remove', function() {
|
||||
setup(function(done) {
|
||||
accountStore.remove(accounts.sync._id).then(done);
|
||||
});
|
||||
|
||||
test('should remove sync button', function(done) {
|
||||
waitFor(() => subject.toolbar.classList.contains('noaccount'), done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('add', function() {
|
||||
setup(function(done) {
|
||||
delete syncAccount._id;
|
||||
accountStore.persist(syncAccount).then(done);
|
||||
});
|
||||
|
||||
test('should show sync button', function(done) {
|
||||
waitFor(() => !subject.toolbar.classList.contains('noaccount'), done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_observeCalendarStore', function() {
|
||||
var children;
|
||||
setup(function(done) {
|
||||
// we must wait until rendering completes
|
||||
subject.onrender = function() {
|
||||
children = subject.calendars.children;
|
||||
nextTick(done);
|
||||
};
|
||||
|
||||
subject.render();
|
||||
});
|
||||
|
||||
suite('calendar update / error', function() {
|
||||
var model;
|
||||
var container;
|
||||
|
||||
setup(function() {
|
||||
model = models.first;
|
||||
container = children[0];
|
||||
});
|
||||
|
||||
test('update with error / without error', function() {
|
||||
model.error = {};
|
||||
store.emit('update', model._id, model);
|
||||
|
||||
assert.ok(
|
||||
container.classList.contains('error'),
|
||||
'has error class'
|
||||
);
|
||||
|
||||
delete model.error;
|
||||
store.emit('update', model._id, model);
|
||||
|
||||
assert.ok(
|
||||
!container.classList.contains('error'),
|
||||
'removes error class'
|
||||
);
|
||||
});
|
||||
|
||||
test('normal flow', function() {
|
||||
var check = children[0].querySelector(
|
||||
'*[type="checkbox"]'
|
||||
);
|
||||
|
||||
model.localDisplayed = false;
|
||||
model.remote.name = 'foo';
|
||||
|
||||
store.emit('update', model._id, model);
|
||||
|
||||
assert.equal(children[0].textContent.trim(), 'foo');
|
||||
assert.isFalse(
|
||||
check.checked
|
||||
);
|
||||
});
|
||||
|
||||
test('toggle l10n', function() {
|
||||
var check = children[1].querySelector('[type="checkbox"]');
|
||||
assert.ok(
|
||||
check.checked,
|
||||
'should be checked'
|
||||
);
|
||||
|
||||
var model = models.local;
|
||||
model.localDisplayed = false;
|
||||
store.emit('update', model._id, model);
|
||||
|
||||
assert.equal(children[1].textContent.trim(), 'Offline calendar');
|
||||
assert.isFalse(
|
||||
check.checked,
|
||||
'should uncheck'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('add', function() {
|
||||
function addModel() {
|
||||
store.emit('add', 'two', model);
|
||||
assert.equal(children.length, 3);
|
||||
var container = children[2];
|
||||
assert.equal(container.textContent.trim(), 'second');
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
var model;
|
||||
setup(function() {
|
||||
model = Factory('calendar', {
|
||||
localDisplayed: false,
|
||||
_id: 'two',
|
||||
remote: { name: 'second' }
|
||||
});
|
||||
|
||||
assert.equal(children.length, 2);
|
||||
});
|
||||
|
||||
test('success', function() {
|
||||
var container = addModel();
|
||||
assert.ok(
|
||||
!container.classList.contains('error'),
|
||||
'does not add error'
|
||||
);
|
||||
});
|
||||
|
||||
test('add with error', function() {
|
||||
model.error = {};
|
||||
var container = addModel();
|
||||
assert.ok(
|
||||
container.classList.contains('error'),
|
||||
'has error'
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('remove', function() {
|
||||
assert.equal(children.length, 2);
|
||||
store.emit('preRemove', models.first._id);
|
||||
store.emit('remove', models.first._id);
|
||||
assert.equal(children.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
suite('syncProgress', function() {
|
||||
|
||||
test('syncStart', function(done) {
|
||||
syncController.on('syncStart', function () {
|
||||
assert.ok(subject.syncProgress.classList.contains('syncing'));
|
||||
assert.equal(subject.syncProgress.getAttribute('data-l10n-id'),
|
||||
'sync-progress-syncing');
|
||||
done();
|
||||
});
|
||||
syncController.emit('syncStart');
|
||||
});
|
||||
|
||||
test('syncComplete', function(done) {
|
||||
syncController.on('syncComplete', function () {
|
||||
assert.equal(subject.syncProgress.getAttribute('data-l10n-id'),
|
||||
'sync-progress-complete');
|
||||
assert.notOk(subject.syncProgress.classList.contains('syncing'));
|
||||
done();
|
||||
});
|
||||
syncController.emit('syncComplete');
|
||||
});
|
||||
});
|
||||
|
||||
suite('#_onCalendarDisplayToggle', function() {
|
||||
var checkboxes;
|
||||
setup(function(done) {
|
||||
subject.render();
|
||||
subject.onrender = function() {
|
||||
checkboxes = {};
|
||||
|
||||
for (var id in models) {
|
||||
checkboxes[id] = subject.calendars.querySelector(
|
||||
'gaia-checkbox[value="' + models[id]._id + '"]'
|
||||
);
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
function checkAsync(id, value) {
|
||||
nextTick(function() {
|
||||
checkboxes[id].checked = !!value;
|
||||
triggerEvent(checkboxes[id], 'change');
|
||||
});
|
||||
}
|
||||
|
||||
test('changing display state to false', function(done) {
|
||||
// the goal is to trigger the change event
|
||||
// multiple times but verify we only persist
|
||||
// once...
|
||||
assert.isTrue(
|
||||
checkboxes.displayed.checked, 'begins checked'
|
||||
);
|
||||
|
||||
// fired when calendar is persisted
|
||||
subject.ondisplaypersist = function(calendar) {
|
||||
done(function() {
|
||||
assert.equal(calendar._id, models.displayed._id);
|
||||
// verify we set it to false and checkbox is hidden.
|
||||
assert.isFalse(calendar.localDisplayed);
|
||||
assert.isFalse(checkboxes.displayed.checked);
|
||||
});
|
||||
};
|
||||
|
||||
checkAsync('displayed', false);
|
||||
checkAsync('displayed', true);
|
||||
checkAsync('displayed', false);
|
||||
});
|
||||
|
||||
test('changing display to true', function(done) {
|
||||
assert.isFalse(
|
||||
checkboxes.hidden.checked,
|
||||
'begins unchecked'
|
||||
);
|
||||
|
||||
checkAsync('hidden', true);
|
||||
|
||||
subject.ondisplaypersist = function(calendar) {
|
||||
done(function() {
|
||||
assert.equal(calendar._id, models.hidden._id);
|
||||
assert.isTrue(calendar.localDisplayed);
|
||||
assert.isTrue(checkboxes.hidden.checked);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('#render', function() {
|
||||
testSupport.calendar.dbFixtures(
|
||||
'account',
|
||||
'Account', {
|
||||
one: {
|
||||
_id: 'one',
|
||||
providerType: 'Local'
|
||||
},
|
||||
|
||||
two: {
|
||||
_id: 'two',
|
||||
providerType: 'Caldav'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var calendars = testSupport.calendar.dbFixtures(
|
||||
'calendar',
|
||||
'Calendar', {
|
||||
one: {
|
||||
accountId: 'one',
|
||||
name: 'First',
|
||||
localDisplayed: true,
|
||||
_id: 1
|
||||
},
|
||||
|
||||
two: {
|
||||
accountId: 'two',
|
||||
name: 'Second',
|
||||
localDisplayed: false,
|
||||
_id: 2,
|
||||
error: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
suite('calendars', function() {
|
||||
var one;
|
||||
var two;
|
||||
var children;
|
||||
|
||||
setup(function(done) {
|
||||
subject.onrender = function() {
|
||||
children = subject.calendars.children;
|
||||
one = children[0];
|
||||
two = children[1];
|
||||
done();
|
||||
};
|
||||
subject.render();
|
||||
});
|
||||
|
||||
test('number of calendars', function() {
|
||||
assert.equal(children.length, 2);
|
||||
});
|
||||
|
||||
test('naming', function() {
|
||||
assert.equal(one.textContent.trim(), calendars.one.name);
|
||||
assert.equal(two.textContent.trim(), calendars.two.name);
|
||||
});
|
||||
|
||||
test('localDisplayed on calendar', function() {
|
||||
assert.isTrue(
|
||||
one.querySelector('*[type="checkbox"]').checked
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
two.querySelector('*[type="checkbox"]').checked
|
||||
);
|
||||
});
|
||||
|
||||
test('error on calendar', function() {
|
||||
assert.ok(
|
||||
two.classList.contains('error'),
|
||||
'if error is present in model render shows it'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
504
gaia/apps/calendar/test/unit/views/single_day_test.js
Executable file
504
gaia/apps/calendar/test/unit/views/single_day_test.js
Executable file
|
|
@ -0,0 +1,504 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var Calc = require('common/calc');
|
||||
var SingleDay = require('views/single_day');
|
||||
var core = require('core');
|
||||
|
||||
suite('Views.SingleDay', function() {
|
||||
var alldaysHolder;
|
||||
var allDayIcon;
|
||||
var date;
|
||||
var dayId;
|
||||
var daysHolder;
|
||||
var subject;
|
||||
|
||||
function sanitize(str) {
|
||||
return str.replace(/\s*\n\s*/gm, ' ');
|
||||
}
|
||||
|
||||
setup(function(done) {
|
||||
daysHolder = document.createElement('div');
|
||||
alldaysHolder = document.createElement('div');
|
||||
allDayIcon = document.createElement('span');
|
||||
allDayIcon.id = 'all-day-icon';
|
||||
date = new Date(2014, 6, 23);
|
||||
dayId = Calc.getDayId(date);
|
||||
|
||||
subject = new SingleDay({
|
||||
date: date,
|
||||
daysHolder: daysHolder,
|
||||
alldaysHolder: alldaysHolder,
|
||||
hourHeight: 50,
|
||||
allDayIcon: allDayIcon,
|
||||
oneDayLabelFormat: 'event-one-day-duration'
|
||||
});
|
||||
|
||||
this.sinon.spy(core.bridge, 'observeDay');
|
||||
this.sinon.spy(window, 'addEventListener');
|
||||
this.sinon.spy(window, 'removeEventListener');
|
||||
this.sinon.spy(subject, 'onactive');
|
||||
this.sinon.spy(subject, 'oninactive');
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.bridge.observeDay.restore();
|
||||
window.addEventListener.restore();
|
||||
window.removeEventListener.restore();
|
||||
subject.onactive.restore();
|
||||
subject.oninactive.restore();
|
||||
subject.destroy();
|
||||
core.db.close();
|
||||
});
|
||||
|
||||
test('#setup', function() {
|
||||
subject.setup();
|
||||
assert.ok(
|
||||
subject.onactive.calledOnce,
|
||||
'activated'
|
||||
);
|
||||
});
|
||||
|
||||
test('#onactive', function() {
|
||||
subject.setup();
|
||||
subject.onactive();
|
||||
subject.onactive();
|
||||
assert.ok(
|
||||
core.bridge.observeDay.calledOnce,
|
||||
'should add listener only once'
|
||||
);
|
||||
assert.ok(
|
||||
core.bridge.observeDay.calledWithExactly(date),
|
||||
'observing day events'
|
||||
);
|
||||
assert.ok(
|
||||
window.addEventListener.calledWithExactly('localized', subject),
|
||||
'observing localized event'
|
||||
);
|
||||
});
|
||||
|
||||
suite('#oninactive', function() {
|
||||
var observer;
|
||||
|
||||
setup(function() {
|
||||
subject._observer = observer = { cancel: sinon.spy() };
|
||||
});
|
||||
|
||||
test('> when inactive', function() {
|
||||
subject.oninactive();
|
||||
subject.oninactive();
|
||||
assert.ok(
|
||||
!observer.cancel.called,
|
||||
'should not execute if not active'
|
||||
);
|
||||
assert.ok(
|
||||
!window.removeEventListener.called,
|
||||
'localized'
|
||||
);
|
||||
});
|
||||
|
||||
test('> when active', function() {
|
||||
subject._isActive = true;
|
||||
subject.oninactive();
|
||||
subject.oninactive();
|
||||
assert.ok(
|
||||
observer.cancel.calledOnce,
|
||||
'should stop listening for date'
|
||||
);
|
||||
assert.ok(
|
||||
window.removeEventListener.calledWithExactly('localized', subject),
|
||||
'localized'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('#append', function() {
|
||||
setup(function(done) {
|
||||
subject.setup();
|
||||
subject.append();
|
||||
// render is async!
|
||||
setTimeout(done);
|
||||
});
|
||||
|
||||
test('> should render', function() {
|
||||
var d = date.toString();
|
||||
|
||||
assert.equal(
|
||||
daysHolder.innerHTML,
|
||||
`<div class="md__day" data-date="${d}"></div>`,
|
||||
'should add day node'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
sanitize(alldaysHolder.innerHTML),
|
||||
sanitize(`<div class="md__allday" data-date="${d}">
|
||||
<h1 class="md__day-name" aria-level="2"
|
||||
id="md__day-name-${subject._instanceID}">23 Wed</h1>
|
||||
<div aria-describedby="md__day-name-${subject._instanceID}"
|
||||
data-l10n-id="create-all-day-event" role="button"
|
||||
class="md__allday-events"></div>
|
||||
</div>`)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('#handleEvent', function() {
|
||||
subject._dayName = { textContent: 'foo' };
|
||||
subject.handleEvent({type: 'localized'});
|
||||
assert.equal(subject._dayName.textContent, '23 Wed');
|
||||
});
|
||||
|
||||
test('#destroy', function() {
|
||||
// it should remove element from DOM and stop listening busytimes
|
||||
subject.setup();
|
||||
subject.append();
|
||||
subject.destroy();
|
||||
assert.equal(daysHolder.innerHTML, '');
|
||||
assert.equal(alldaysHolder.innerHTML, '');
|
||||
assert.ok(
|
||||
subject.oninactive.calledOnce,
|
||||
'should deactivate'
|
||||
);
|
||||
});
|
||||
|
||||
test('#_render', function() {
|
||||
setup(function(done) {
|
||||
subject.setup();
|
||||
subject.append();
|
||||
setTimeout(done);
|
||||
});
|
||||
|
||||
test('> should render', function() {
|
||||
var data = {
|
||||
amount: 3,
|
||||
basic: [
|
||||
makeRecord('Dolor Amet', '4:00', '6:00', 1),
|
||||
makeRecord('Lorem Ipsum', '5:00', '6:00')
|
||||
],
|
||||
allday: [
|
||||
makeAlldayRecord('Curabitur')
|
||||
]
|
||||
};
|
||||
var makeFirstEventID = makeID.bind(this, subject, data.basic[0]);
|
||||
var makeSecondEventID = makeID.bind(this, subject, data.basic[1]);
|
||||
var makeAllDayEventID = makeID.bind(this, subject, data.allday[0]);
|
||||
|
||||
// notice that we are testing the method indirectly (the important thing
|
||||
// to check is if the view updates when we receive new data)
|
||||
subject._observer.write(data);
|
||||
|
||||
assert.lengthOf(
|
||||
daysHolder.querySelectorAll('.md__event'), 2, '0: events'
|
||||
);
|
||||
assert.lengthOf(
|
||||
alldaysHolder.querySelectorAll('.md__event'), 1, '0: all'
|
||||
);
|
||||
|
||||
// testing the whole markup is enough to check if position and overlaps
|
||||
// are handled properly and also makes sure all the data is passed to the
|
||||
// templates, a drawback is that if we change the markup we need to update
|
||||
// the tests (might catch differences that are not regressions)
|
||||
|
||||
var days = daysHolder.querySelectorAll('.md__day');
|
||||
assert.lengthOf(days, 1, 'single day');
|
||||
assert.equal(days[0].dataset.date, date.toString(), '[data-date]');
|
||||
|
||||
var busytimes = days[0].querySelectorAll('.md__event');
|
||||
assert.lengthOf(busytimes, 2, 'busytimes');
|
||||
|
||||
// busytime #1
|
||||
var busy = busytimes[0];
|
||||
|
||||
// position/size is enough to test overlaps
|
||||
assert.equal(busy.style.height, '99.9px', '1: height');
|
||||
assert.equal(busy.style.top, '200px', '1: top');
|
||||
assert.equal(busy.style.width, '50%', '1: width');
|
||||
assert.equal(busy.style.left, '50%', '1: left');
|
||||
assert.include(
|
||||
busy.href, '/event/show/' + data.basic[0].busytime._id, '1: href');
|
||||
|
||||
var labels = busy.getAttribute('aria-labelledby');
|
||||
assert.include(labels, makeFirstEventID('title'), '1: label title');
|
||||
assert.include(labels, makeFirstEventID('location'), '1: label location');
|
||||
assert.include(labels, makeFirstEventID('icon'), '1: label icon');
|
||||
assert.include(labels, makeFirstEventID('description'), '1: label desc');
|
||||
|
||||
assert.include(busy.className, 'has-alarms', '1: class');
|
||||
assert.include(busy.className, 'has-overlaps', '1: class');
|
||||
|
||||
var remote = data.basic[0].event.remote;
|
||||
|
||||
var title = busy.querySelector('#' + makeFirstEventID('title'));
|
||||
assert.equal(title.textContent.trim(), remote.title, '1: title');
|
||||
|
||||
var location = busy.querySelector('#' + makeFirstEventID('location'));
|
||||
assert.equal(location.textContent.trim(), remote.location, '1: location');
|
||||
|
||||
var icon = busy.querySelector('#' + makeFirstEventID('icon'));
|
||||
assert.include(icon.className, 'icon-calendar-alarm', '1: icon');
|
||||
assert.equal(icon.getAttribute('aria-hidden'), 'true', '1: icon hidden');
|
||||
|
||||
var description = busy.querySelector(
|
||||
'#' + makeFirstEventID('description')
|
||||
);
|
||||
assert.equal(
|
||||
description.getAttribute('aria-hidden'), 'true', '1: desc hidden');
|
||||
assert.equal(
|
||||
description.dataset.l10nId, 'event-one-day-duration', '1: desc l10nId'
|
||||
);
|
||||
assert.equal(
|
||||
description.dataset.l10nArgs,
|
||||
'{"startDate":"Wednesday, July 23, 2014","startTime":"04:00",' +
|
||||
'"endDate":"Wednesday, July 23, 2014","endTime":"06:00"}',
|
||||
'1: desc l10nArgs'
|
||||
);
|
||||
|
||||
// busytime #2
|
||||
busy = busytimes[1];
|
||||
|
||||
// position/size is enough to test overlaps
|
||||
assert.equal(busy.style.height, '49.9px', '2: height');
|
||||
assert.equal(busy.style.top, '250px', '2: top');
|
||||
assert.equal(busy.style.width, '50%', '2: width');
|
||||
assert.equal(busy.style.left, '0%', '2: left');
|
||||
assert.include(
|
||||
busy.href, '/event/show/' + data.basic[1].busytime._id, '2: href');
|
||||
|
||||
labels = busy.getAttribute('aria-labelledby');
|
||||
assert.include(labels, makeSecondEventID('title'), '2: label title');
|
||||
assert.include(
|
||||
labels, makeSecondEventID('location'), '2: label location'
|
||||
);
|
||||
assert.include(labels, makeSecondEventID('description'), '2: label desc');
|
||||
|
||||
assert.include(busy.className, 'has-overlaps', '2: class');
|
||||
|
||||
remote = data.basic[1].event.remote;
|
||||
|
||||
title = busy.querySelector('#' + makeSecondEventID('title'));
|
||||
assert.equal(title.textContent.trim(), remote.title, '2: title');
|
||||
|
||||
location = busy.querySelector('#' + makeSecondEventID('location'));
|
||||
assert.equal(location.textContent.trim(), remote.location, '2: location');
|
||||
|
||||
icon = busy.querySelector('#' + makeSecondEventID('icon'));
|
||||
assert.isNull(icon, '2: icon');
|
||||
|
||||
description = busy.querySelector('#' + makeSecondEventID('description'));
|
||||
assert.equal(
|
||||
description.getAttribute('aria-hidden'), 'true', '2: desc hidden');
|
||||
assert.equal(
|
||||
description.dataset.l10nId, 'event-one-day-duration', '2: desc l10nId'
|
||||
);
|
||||
assert.equal(
|
||||
description.dataset.l10nArgs,
|
||||
'{"startDate":"Wednesday, July 23, 2014","startTime":"05:00",' +
|
||||
'"endDate":"Wednesday, July 23, 2014","endTime":"06:00"}',
|
||||
'2: desc l10nArgs'
|
||||
);
|
||||
|
||||
var id = subject._instanceID;
|
||||
|
||||
var dayName = alldaysHolder.querySelector('.md__day-name');
|
||||
assert.equal(dayName.getAttribute('aria-level'), '2', '3: day level');
|
||||
assert.equal(dayName.id, `md__day-name-${id}`, '3: day id');
|
||||
assert.equal(dayName.textContent.trim(), '23 Wed', '3: day');
|
||||
|
||||
var wrapper = alldaysHolder.querySelector('.md__allday-events');
|
||||
assert.equal(
|
||||
wrapper.getAttribute('aria-labelledby'),
|
||||
`all-day-icon md__day-name-${id}`,
|
||||
'3: wrapper aria-labelledby'
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.getAttribute('aria-describedby'),
|
||||
`md__day-name-${id}`,
|
||||
'3: wrapper aria-describedby'
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.dataset.l10nId,
|
||||
'create-all-day-event',
|
||||
'3: wrapper data-l10n-id'
|
||||
);
|
||||
assert.equal(wrapper.getAttribute('role'), 'listbox', '3: wrapper role');
|
||||
assert.equal(wrapper.childNodes.length, 1, '3: wrapper childNodes');
|
||||
|
||||
busy = wrapper.firstChild;
|
||||
assert.equal(busy.getAttribute('role'), 'option', '4: busy role');
|
||||
assert.include(busy.className, 'md__event', '4: busy md__event');
|
||||
assert.include(busy.className, 'is-allday', '4: busy is-allday');
|
||||
assert.equal(
|
||||
busy.style.borderColor,
|
||||
'rgb(0, 255, 204)',
|
||||
'4: busy border color'
|
||||
);
|
||||
assert.equal(
|
||||
busy.style.backgroundColor,
|
||||
'rgba(0, 255, 204, 0.2)',
|
||||
'4: busy background color'
|
||||
);
|
||||
assert.include(
|
||||
busy.getAttribute('aria-labelledby'),
|
||||
makeAllDayEventID('location'),
|
||||
'4: busy location label'
|
||||
);
|
||||
assert.include(
|
||||
busy.getAttribute('aria-labelledby'),
|
||||
makeAllDayEventID('title'),
|
||||
'4: busy title label'
|
||||
);
|
||||
assert.include(
|
||||
busy.getAttribute('aria-labelledby'),
|
||||
makeAllDayEventID('description'),
|
||||
'4: busy description label'
|
||||
);
|
||||
|
||||
remote = data.allday[0].event.remote;
|
||||
|
||||
title = busy.querySelector('.md__event-title');
|
||||
assert.equal(
|
||||
title.textContent.trim(),
|
||||
remote.title,
|
||||
'4: title'
|
||||
);
|
||||
assert.equal(
|
||||
title.id,
|
||||
makeAllDayEventID('title'),
|
||||
'4: title id'
|
||||
);
|
||||
|
||||
location = busy.querySelector('.md__event-location');
|
||||
assert.equal(
|
||||
location.textContent.trim(),
|
||||
remote.location,
|
||||
'4: location'
|
||||
);
|
||||
assert.equal(
|
||||
location.id,
|
||||
makeAllDayEventID('location'),
|
||||
'4: location id'
|
||||
);
|
||||
|
||||
description = busy.querySelector('#' + makeAllDayEventID('description'));
|
||||
assert.equal(
|
||||
description.getAttribute('aria-hidden'),
|
||||
'true',
|
||||
'4: description aria-hidden'
|
||||
);
|
||||
assert.equal(
|
||||
description.getAttribute('data-l10n-id'),
|
||||
'event-multiple-day-duration',
|
||||
'4: description data-l10n-id'
|
||||
);
|
||||
assert.equal(
|
||||
description.dataset.l10nArgs,
|
||||
'{"startDate":"Wednesday, July 23, 2014","startTime":"00:00",' +
|
||||
'"endDate":"Thursday, July 24, 2014","endTime":"00:00"}',
|
||||
'4: description data-l10n-id'
|
||||
);
|
||||
|
||||
data = {
|
||||
amount: 2,
|
||||
basic: [
|
||||
makeRecord('Lorem Ipsum', '5:00', '6:00'),
|
||||
makeRecord('Maecennas', '6:00', '17:00', 1)
|
||||
],
|
||||
allday: []
|
||||
};
|
||||
// we always send all the events for that day and redraw whole view
|
||||
subject._observer.write(data);
|
||||
|
||||
// it's enough to check only the new event and the amount of busytimes
|
||||
// inside each holder (just to ensure we are removing old elements)
|
||||
busytimes = daysHolder.querySelectorAll('.md__event');
|
||||
assert.lengthOf(busytimes, 2, '5: events');
|
||||
assert.lengthOf(
|
||||
alldaysHolder.querySelectorAll('.md__event'), 0, '5: all'
|
||||
);
|
||||
assert.equal(
|
||||
busytimes[1].querySelector('.md__event-title').textContent.trim(),
|
||||
data.basic[1].event.remote.title,
|
||||
'5: event title'
|
||||
);
|
||||
});
|
||||
|
||||
test('> partial hour', function() {
|
||||
subject._observer.write({
|
||||
amount: 4,
|
||||
basic: [
|
||||
makeRecord('Lorem Ipsum', '5:00', '5:15'),
|
||||
makeRecord('Maecennas', '6:00', '6:25'),
|
||||
makeRecord('Dolor', '6:30', '7:00'),
|
||||
makeRecord('Amet', '7:00', '7:50')
|
||||
],
|
||||
allday: []
|
||||
});
|
||||
|
||||
assert.include(
|
||||
daysHolder.innerHTML,
|
||||
'is-partial is-partial-micro',
|
||||
'smaller than 18min'
|
||||
);
|
||||
|
||||
assert.include(
|
||||
daysHolder.innerHTML,
|
||||
'is-partial is-partial-tiny',
|
||||
'between 18-30min'
|
||||
);
|
||||
|
||||
assert.include(
|
||||
daysHolder.innerHTML,
|
||||
'is-partial is-partial-small',
|
||||
'between 30-45min'
|
||||
);
|
||||
|
||||
assert.include(
|
||||
daysHolder.innerHTML,
|
||||
'is-partial"',
|
||||
'longer than 45min'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function makeID(subject, event, postfix) {
|
||||
return ['md__event', event.busytime._id, postfix, subject._instanceID]
|
||||
.join('-').replace(/\s+/g, '-');
|
||||
}
|
||||
|
||||
function makeRecord(title, startTime, endTime, alarmsLength) {
|
||||
var startDate = new Date(date);
|
||||
var [startHour, startMinutes] = startTime.split(':');
|
||||
startDate.setHours(startHour, startMinutes);
|
||||
|
||||
var endDate = new Date(date);
|
||||
var [endHour, endMinutes] = endTime.split(':');
|
||||
endDate.setHours(endHour, endMinutes);
|
||||
|
||||
return {
|
||||
color: '#00ffcc',
|
||||
busytime: {
|
||||
_id: (title + '-' + startTime + '-' + endTime).replace(/[\s:]+/g, '-'),
|
||||
startDate: startDate,
|
||||
endDate: endDate
|
||||
},
|
||||
event: {
|
||||
calendarId: 'local-first',
|
||||
remote: {
|
||||
title: title,
|
||||
location: 'Mars',
|
||||
alarms: new Array(alarmsLength || 0)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function makeAlldayRecord(title, alarmsLength) {
|
||||
var record = makeRecord(title, '0:00', '0:00', alarmsLength);
|
||||
var endDate = record.busytime.endDate;
|
||||
endDate.setDate(endDate.getDate() + 1);
|
||||
return record;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
138
gaia/apps/calendar/test/unit/views/single_month_test.js
Executable file
138
gaia/apps/calendar/test/unit/views/single_month_test.js
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var SingleMonth = require('views/single_month');
|
||||
|
||||
suite('Views.SingleMonth', function() {
|
||||
var core;
|
||||
var subject;
|
||||
var container;
|
||||
|
||||
setup(function() {
|
||||
core = testSupport.calendar.core();
|
||||
container = document.createElement('div');
|
||||
subject = new SingleMonth({
|
||||
date: new Date(2014, 6, 1),
|
||||
container: container
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.destroy();
|
||||
container.innerHTML = '';
|
||||
});
|
||||
|
||||
test('#create', function() {
|
||||
subject.create();
|
||||
|
||||
var el = subject.element;
|
||||
assert.equal(el.className, 'month');
|
||||
assert.equal(el.getAttribute('role'), 'grid');
|
||||
assert.equal(el.getAttribute('aria-labelledby'), 'current-month-year');
|
||||
assert.equal(el.getAttribute('aria-readonly'), 'true');
|
||||
|
||||
var headers = el.querySelectorAll('li[role="columnheader"]');
|
||||
Array.forEach(headers, (li, i) => {
|
||||
assert.equal(li.dataset.l10nId, `weekday-${i}-single-char`);
|
||||
});
|
||||
|
||||
var days = el.querySelectorAll('.day');
|
||||
assert.lengthOf(days, 35);
|
||||
assert.lengthOf(subject.days, 35);
|
||||
|
||||
// one ol is used for the table header, 5 for the weeks
|
||||
assert.lengthOf(el.querySelectorAll('ol[role="row"]'), 6);
|
||||
});
|
||||
|
||||
suite('activate/deactivate', function() {
|
||||
var days;
|
||||
var tc;
|
||||
|
||||
setup(function() {
|
||||
tc = core.timeController;
|
||||
core.timeController = {
|
||||
on: sinon.spy(),
|
||||
off: sinon.spy()
|
||||
};
|
||||
|
||||
function makeDay() {
|
||||
return { activate: sinon.spy(), deactivate: sinon.spy() };
|
||||
}
|
||||
|
||||
days = subject.days;
|
||||
subject.days = [ makeDay(), makeDay() ];
|
||||
|
||||
sinon.stub(subject, '_onSelectedDayChange');
|
||||
sinon.spy(subject, 'oninactive');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.timeController = tc;
|
||||
subject.days = days;
|
||||
subject._onSelectedDayChange.restore();
|
||||
subject.oninactive.restore();
|
||||
});
|
||||
|
||||
test('#activate', function() {
|
||||
subject.activate();
|
||||
sinon.assert.calledOnce(subject.days[0].activate, 'activate 1st day');
|
||||
sinon.assert.calledOnce(subject.days[1].activate, 'activate 2nd day');
|
||||
sinon.assert.calledWith(
|
||||
core.timeController.on,
|
||||
'selectedDayChange',
|
||||
subject
|
||||
);
|
||||
// view might be disabled with a selected day, or view might be enabled
|
||||
// with a preselected day
|
||||
sinon.assert.calledOnce(subject._onSelectedDayChange);
|
||||
});
|
||||
|
||||
test('#deactivate: not active', function() {
|
||||
subject.deactivate();
|
||||
sinon.assert.notCalled(subject.oninactive);
|
||||
sinon.assert.notCalled(subject.days[0].deactivate);
|
||||
sinon.assert.notCalled(core.timeController.off);
|
||||
});
|
||||
|
||||
test('#deactivate: active', function() {
|
||||
subject.activate();
|
||||
subject.deactivate();
|
||||
sinon.assert.calledOnce(subject.oninactive);
|
||||
sinon.assert.calledOnce(subject.days[0].deactivate);
|
||||
sinon.assert.calledWith(
|
||||
core.timeController.off,
|
||||
'selectedDayChange',
|
||||
subject
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('selectedDayChange', function() {
|
||||
subject.create();
|
||||
|
||||
// no days selected by default
|
||||
var selected = subject.element.querySelectorAll('li.selected');
|
||||
assert.lengthOf(selected, 0);
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'selectedDayChange',
|
||||
data: [ new Date(2014, 6, 7) ]
|
||||
});
|
||||
|
||||
selected = subject.element.querySelectorAll('li.selected');
|
||||
assert.lengthOf(selected, 1);
|
||||
assert.equal(selected[0].dataset.date, 'd-2014-6-7');
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'selectedDayChange',
|
||||
data: [ new Date(2014, 6, 23) ]
|
||||
});
|
||||
|
||||
selected = subject.element.querySelectorAll('li.selected');
|
||||
assert.lengthOf(selected, 1);
|
||||
assert.equal(selected[0].dataset.date, 'd-2014-6-23');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
170
gaia/apps/calendar/test/unit/views/time_header_test.js
Executable file
170
gaia/apps/calendar/test/unit/views/time_header_test.js
Executable file
|
|
@ -0,0 +1,170 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
requireCommon('test/synthetic_gestures.js');
|
||||
var intl = require('intl');
|
||||
|
||||
var TimeHeader = require('views/time_header');
|
||||
var View = require('view');
|
||||
var core = require('core');
|
||||
|
||||
suite('Views.TimeHeader', function() {
|
||||
var subject;
|
||||
var controller;
|
||||
var date = new Date(2012, 0, 1);
|
||||
var monthTitle;
|
||||
|
||||
suiteSetup(function() {
|
||||
intl.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
var el = document.getElementById('test');
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var div = document.createElement('div');
|
||||
div.id = 'test';
|
||||
div.innerHTML = [
|
||||
'<div id="wrapper"></div>',
|
||||
'<gaia-header id="time-header" action="menu">',
|
||||
'<h1></h1>',
|
||||
'</gaia-header>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(div);
|
||||
|
||||
controller = core.timeController;
|
||||
|
||||
subject = new TimeHeader();
|
||||
|
||||
controller.move(date);
|
||||
monthTitle = window.IntlHelper.get('multi-month-view-header-format').
|
||||
format(date);
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.instanceOf(subject, View);
|
||||
assert.ok(subject.element);
|
||||
assert.equal(
|
||||
subject.element, document.querySelector('#time-header')
|
||||
);
|
||||
});
|
||||
|
||||
test('#title', function() {
|
||||
assert.ok(subject.title);
|
||||
});
|
||||
|
||||
test('#getScale', function() {
|
||||
var out = subject.getScale('month');
|
||||
assert.deepEqual(
|
||||
out,
|
||||
monthTitle
|
||||
);
|
||||
});
|
||||
|
||||
test('#getScale for day', function() {
|
||||
controller.move(new Date(2012, 0, 30));
|
||||
var compare = window.IntlHelper.get('day-view-header-format').
|
||||
format(new Date(2012, 0, 30));
|
||||
var out = subject.getScale('day');
|
||||
assert.equal(out, compare);
|
||||
// 20 chars seems to be the maximum with current layout (see bug 951423)
|
||||
assert.operator(out.length, '<', 21,
|
||||
'header should not have too many chars');
|
||||
});
|
||||
|
||||
test('#getScale for week', function() {
|
||||
controller.move(new Date(2012, 0, 15));
|
||||
var out = subject.getScale('week');
|
||||
var compare = window.IntlHelper.get('multi-month-view-header-format').
|
||||
format(new Date(2012, 0, 30));
|
||||
assert.equal(out, compare);
|
||||
});
|
||||
|
||||
// When week starts in one month and ends in another we need a special format
|
||||
test('#getScale for week - multiple months', function() {
|
||||
controller.move(new Date(2012, 0, 30));
|
||||
var out = subject.getScale('week');
|
||||
var formatter = window.IntlHelper.get('multi-month-view-header-format');
|
||||
var compare = formatter.format(new Date(2012, 0, 30));
|
||||
compare += ' ' + formatter.format(new Date(2012, 1, 4));
|
||||
assert.equal(out, compare);
|
||||
});
|
||||
|
||||
test('#getScale for week - month ending on Wednesday', function() {
|
||||
controller.move(new Date(2013, 6, 30));
|
||||
var out = subject.getScale('week');
|
||||
var formatter = window.IntlHelper.get('multi-month-view-header-format');
|
||||
assert.equal(
|
||||
out,
|
||||
formatter.format(new Date(2013, 6, 28)) + ' ' +
|
||||
formatter.format(new Date(2013, 7, 3))
|
||||
);
|
||||
});
|
||||
|
||||
test('#_updateTitle', function() {
|
||||
subject._updateTitle();
|
||||
|
||||
assert.equal(
|
||||
subject.title.dataset.date,
|
||||
controller.position.toString(),
|
||||
'sets element date'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
subject.title.dataset.l10nDateFormat,
|
||||
subject.scales.month,
|
||||
'sets element scale'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
subject.title.textContent,
|
||||
subject.getScale('month')
|
||||
);
|
||||
});
|
||||
|
||||
suite('changing scales', function() {
|
||||
|
||||
var calledWith;
|
||||
|
||||
setup(function() {
|
||||
controller.move(date);
|
||||
controller.scale = 'year';
|
||||
|
||||
subject._updateTitle = function() {
|
||||
calledWith = arguments;
|
||||
};
|
||||
// setup initial scale
|
||||
subject.render();
|
||||
calledWith = null;
|
||||
});
|
||||
|
||||
test('initial change', function() {
|
||||
controller.move(new Date(
|
||||
date.getFullYear(),
|
||||
1
|
||||
));
|
||||
|
||||
assert.ok(!calledWith, 'dont re-render out of scale');
|
||||
controller.move(new Date(2020, 1));
|
||||
assert.ok(calledWith);
|
||||
});
|
||||
|
||||
test('change scale', function() {
|
||||
controller.scale = 'month';
|
||||
assert.ok(calledWith);
|
||||
calledWith = null;
|
||||
|
||||
controller.move(new Date(
|
||||
date.getFullYear(),
|
||||
date.getMonth() + 1
|
||||
));
|
||||
|
||||
assert.ok(calledWith);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
322
gaia/apps/calendar/test/unit/views/view_event_test.js
Executable file
322
gaia/apps/calendar/test/unit/views/view_event_test.js
Executable file
|
|
@ -0,0 +1,322 @@
|
|||
/* global suiteTemplate, MockMozIntl */
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_moz_intl.js');
|
||||
|
||||
var EventBase = require('views/event_base');
|
||||
var View = require('view');
|
||||
var ViewEvent = require('views/view_event');
|
||||
var core = require('core');
|
||||
var router = require('router');
|
||||
var intl = require('intl');
|
||||
|
||||
require('dom!show_event');
|
||||
|
||||
suite('Views.ViewEvent', function() {
|
||||
var subject;
|
||||
var controller;
|
||||
|
||||
var event;
|
||||
var account;
|
||||
var calendar;
|
||||
var busytime;
|
||||
var provider;
|
||||
|
||||
var remote;
|
||||
var eventStore;
|
||||
var calendarStore;
|
||||
var accountStore;
|
||||
var realMozIntl;
|
||||
|
||||
function getEl(name) {
|
||||
return subject.getEl(name);
|
||||
}
|
||||
|
||||
function contentValue(name) {
|
||||
var field = getEl(name).querySelector('.content');
|
||||
return field.textContent;
|
||||
}
|
||||
|
||||
var triggerEvent;
|
||||
suiteSetup(function() {
|
||||
realMozIntl = window.mozIntl;
|
||||
window.mozIntl = MockMozIntl;
|
||||
intl.init();
|
||||
testSupport.calendar.core();
|
||||
triggerEvent = testSupport.calendar.triggerEvent;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.mozIntl = realMozIntl;
|
||||
});
|
||||
|
||||
|
||||
var realGo;
|
||||
|
||||
teardown(function() {
|
||||
router.go = realGo;
|
||||
});
|
||||
|
||||
suiteTemplate('show-event', {
|
||||
id: 'event-view'
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
realGo = router.go;
|
||||
|
||||
var storeFactory = core.storeFactory;
|
||||
eventStore = storeFactory.get('Event');
|
||||
accountStore = storeFactory.get('Account');
|
||||
calendarStore = storeFactory.get('Calendar');
|
||||
provider = core.providerFactory.get('Mock');
|
||||
|
||||
controller = core.timeController;
|
||||
|
||||
subject = new ViewEvent();
|
||||
|
||||
core.db.open(done);
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
testSupport.calendar.clearStore(
|
||||
core.db,
|
||||
['accounts', 'calendars', 'events', 'busytimes', 'alarms'],
|
||||
function() {
|
||||
core.db.close();
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
testSupport.calendar.accountEnvironment();
|
||||
testSupport.calendar.eventEnvironment(
|
||||
// busytime
|
||||
{
|
||||
startDate: new Date(2012, 1, 1, 1),
|
||||
endDate: new Date(2012, 1, 5, 1)
|
||||
},
|
||||
// event
|
||||
{
|
||||
startDate: new Date(2012, 1, 1, 1),
|
||||
endDate: new Date(2012, 1, 5, 1)
|
||||
}
|
||||
);
|
||||
|
||||
setup(function() {
|
||||
remote = this.event.remote;
|
||||
event = this.event;
|
||||
calendar = this.calendar;
|
||||
account = this.account;
|
||||
busytime = this.busytime;
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.instanceOf(subject, View);
|
||||
assert.instanceOf(subject, EventBase);
|
||||
assert.equal(subject._changeToken, 0);
|
||||
|
||||
assert.ok(subject._els, 'has elements');
|
||||
});
|
||||
|
||||
test('.primaryButton', function() {
|
||||
assert.ok(subject.primaryButton);
|
||||
});
|
||||
|
||||
test('.header', function() {
|
||||
assert.ok(subject.header);
|
||||
});
|
||||
|
||||
test('.fieldRoot', function() {
|
||||
assert.ok(subject.fieldRoot);
|
||||
assert.equal(subject.fieldRoot, subject.element);
|
||||
});
|
||||
|
||||
test('#setContent', function() {
|
||||
subject.setContent('title', '<b>text</b>');
|
||||
assert.equal(
|
||||
subject.getEl('title').querySelector('.content').innerHTML,
|
||||
'<b>text</b>'
|
||||
);
|
||||
|
||||
subject.setContent('title', '<b>text</b>', 'innerHTML');
|
||||
assert.equal(
|
||||
subject.getEl('title').querySelector('.content').innerHTML,
|
||||
'<b>text</b>'
|
||||
);
|
||||
});
|
||||
|
||||
test('#_getEl', function() {
|
||||
var expected = subject.fieldRoot.querySelector('.title');
|
||||
assert.ok(expected);
|
||||
assert.equal(expected.tagName.toLowerCase(), 'li');
|
||||
|
||||
var result = subject.getEl('title');
|
||||
|
||||
assert.equal(result, expected);
|
||||
assert.equal(result, subject.getEl('title'));
|
||||
assert.equal(subject._els.title, expected);
|
||||
});
|
||||
|
||||
suite('#_updateUI', function() {
|
||||
var list;
|
||||
|
||||
setup(function() {
|
||||
list = subject.element.classList;
|
||||
});
|
||||
|
||||
function updatesValues(overrides, isAllDay, capabilities) {
|
||||
capabilities = capabilities || { canUpdate: true };
|
||||
|
||||
var expected = {
|
||||
title: remote.title,
|
||||
location: remote.location,
|
||||
currentCalendar: calendar.remote.name,
|
||||
description: remote.description
|
||||
};
|
||||
|
||||
var allDayHidden = [
|
||||
'startTime',
|
||||
'endTime'
|
||||
];
|
||||
|
||||
if (overrides) {
|
||||
for (var key in overrides) {
|
||||
expected[key] = overrides[key];
|
||||
}
|
||||
}
|
||||
|
||||
function verify() {
|
||||
if (capabilities.canCreateEvent) {
|
||||
expected.calendarId = event.calendarId;
|
||||
}
|
||||
|
||||
function replaceCaps($1) { return '-' + $1.toLowerCase(); }
|
||||
for (var key in expected) {
|
||||
|
||||
// To dash-delimited
|
||||
var fieldKey = key.replace(/([A-Z])/g, replaceCaps);
|
||||
|
||||
if (isAllDay && allDayHidden.indexOf(key) !== -1) {
|
||||
assert.equal(
|
||||
contentValue(fieldKey),
|
||||
'',
|
||||
'time element should be empty for all-day: "' + key + '"'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expected.hasOwnProperty(key)) {
|
||||
assert.equal(
|
||||
contentValue(fieldKey),
|
||||
expected[key],
|
||||
'should set "' + key + '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
subject.onfirstseen();
|
||||
subject._useModel({
|
||||
busytime: busytime,
|
||||
event: event,
|
||||
calendar: calendar,
|
||||
capabilities: capabilities
|
||||
});
|
||||
verify();
|
||||
}
|
||||
|
||||
test('event view fields', function() {
|
||||
updatesValues(null, null);
|
||||
});
|
||||
|
||||
test('readonly', function() {
|
||||
updatesValues(null, null, {
|
||||
canUpdateEvent: false,
|
||||
canCreateEvent: false
|
||||
});
|
||||
});
|
||||
|
||||
test('event description with html', function() {
|
||||
event.remote.description = '<strong>hamburger</strong>';
|
||||
|
||||
updatesValues(
|
||||
{ description: '<strong>hamburger</strong>' },
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
test('alarms are displayed', function() {
|
||||
|
||||
event.remote.alarms = [
|
||||
{trigger: 0},
|
||||
{trigger: -60}
|
||||
];
|
||||
|
||||
subject.onfirstseen();
|
||||
subject._useModel({
|
||||
busytime: busytime,
|
||||
event: event,
|
||||
capabilities: { canUpdate: true }
|
||||
});
|
||||
|
||||
var alarmChildren = getEl('alarms').querySelector('.content').children;
|
||||
|
||||
assert.equal(
|
||||
alarmChildren.length,
|
||||
2
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
alarmChildren[0].textContent.trim(),
|
||||
navigator.mozL10n.get('alarm-at-event-standard')
|
||||
);
|
||||
assert.equal(
|
||||
alarmChildren[1].textContent.trim(),
|
||||
navigator.mozL10n.get('minutes-before', {value: 1})
|
||||
);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('navigation', function() {
|
||||
test('cancel button step back', function(done) {
|
||||
|
||||
router.go = function(place) {
|
||||
assert.equal(place, '/foo', 'redirects to proper location');
|
||||
done();
|
||||
};
|
||||
|
||||
subject._returnTop = '/foo';
|
||||
|
||||
triggerEvent(subject.header, 'action');
|
||||
});
|
||||
|
||||
test('cancel button return top', function(done) {
|
||||
|
||||
router.go = function(place) {
|
||||
assert.equal(place, '/bar', 'redirects to proper location');
|
||||
done();
|
||||
};
|
||||
|
||||
subject._returnTo = '/bar';
|
||||
|
||||
triggerEvent(subject.header, 'action');
|
||||
});
|
||||
|
||||
test('edit button click', function(done) {
|
||||
|
||||
router.go = function(place) {
|
||||
assert.equal(place, '/event/edit/funtime/', 'redirects to event page');
|
||||
done();
|
||||
};
|
||||
|
||||
subject.busytime = {
|
||||
_id: 'funtime'
|
||||
};
|
||||
|
||||
triggerEvent(subject.primaryButton, 'click');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
46
gaia/apps/calendar/test/unit/views/week_test.js
Executable file
46
gaia/apps/calendar/test/unit/views/week_test.js
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var Calc = require('common/calc');
|
||||
var Week = require('views/week');
|
||||
|
||||
suite('Views.Week', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
subject = new Week();
|
||||
});
|
||||
|
||||
suite('#_calcBaseDate', function() {
|
||||
test('Get same date if equal to base date', function() {
|
||||
var date = new Date(1983, 8, 8);
|
||||
subject.baseDate = date;
|
||||
var baseDate = subject._calcBaseDate(date);
|
||||
assert.isTrue(Calc.isSameDate(baseDate, date));
|
||||
});
|
||||
|
||||
test('Get same date if it is Saturday', function() {
|
||||
// It is Saturday.
|
||||
var date = new Date(1983, 8, 10);
|
||||
var baseDate = subject._calcBaseDate(date);
|
||||
assert.isTrue(Calc.isSameDate(baseDate, date));
|
||||
});
|
||||
|
||||
test('Get same date if it is Sunday', function() {
|
||||
// It is Sunday.
|
||||
var date = new Date(1983, 8, 11);
|
||||
var baseDate = subject._calcBaseDate(date);
|
||||
assert.isTrue(Calc.isSameDate(baseDate, date));
|
||||
});
|
||||
|
||||
test('Get monday if date is between Mon to Fri', function() {
|
||||
// It is Thursday.
|
||||
var date = new Date(1983, 8, 8);
|
||||
var baseDate = subject._calcBaseDate(date);
|
||||
assert.equal(baseDate.getDay(), 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Loading…
Reference in a new issue