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
139
gaia/apps/calendar/test/unit/support/calendar.js
Executable file
139
gaia/apps/calendar/test/unit/support/calendar.js
Executable file
|
|
@ -0,0 +1,139 @@
|
|||
define(function(require, exports) {
|
||||
'use strict';
|
||||
|
||||
var Db = require('db');
|
||||
var Factory = require('test/support/factory');
|
||||
var MockProvider = require('test/support/mock_provider');
|
||||
var app = require('app');
|
||||
var core = require('core');
|
||||
|
||||
require('test/support/factories/all');
|
||||
|
||||
exports._lastEnvId = 0;
|
||||
|
||||
exports.core = function() {
|
||||
var pendingManager = app.pendingManager;
|
||||
if (pendingManager) {
|
||||
// hack to ensure clean tests
|
||||
pendingManager.objects.forEach(item => pendingManager.unregister(item));
|
||||
}
|
||||
|
||||
if (core.db && core.db.isOpen) {
|
||||
core.db.close();
|
||||
}
|
||||
|
||||
app.setupCore('b2g-test-calendar');
|
||||
core.providerFactory.providers.Mock = new MockProvider();
|
||||
return core;
|
||||
};
|
||||
|
||||
exports.accountEnvironment = function(accOverrides, calOverrides) {
|
||||
accOverrides = accOverrides || {};
|
||||
accOverrides.providerType = accOverrides.providerType || 'Mock';
|
||||
calOverrides = calOverrides || {};
|
||||
|
||||
setup(function(done) {
|
||||
var id = ++exports._lastEnvId;
|
||||
accOverrides._id = id;
|
||||
calOverrides.accountId = id;
|
||||
|
||||
var trans = core.db.transaction(['accounts', 'calendars'], 'readwrite');
|
||||
trans.oncomplete = () => done();
|
||||
trans.onerror = event => done(event.target.error);
|
||||
|
||||
var account = this.account = Factory('account', accOverrides);
|
||||
var calendar = this.calendar = Factory('calendar', calOverrides);
|
||||
var storeFactory = core.storeFactory;
|
||||
var accountStore = storeFactory.get('Account');
|
||||
var calendarStore = storeFactory.get('Calendar');
|
||||
accountStore.persist(account, trans);
|
||||
calendarStore.persist(calendar, trans);
|
||||
});
|
||||
};
|
||||
|
||||
exports.eventEnvironment = function(busytimeOverrides, eventOverrides) {
|
||||
eventOverrides = eventOverrides || {};
|
||||
eventOverrides._id = eventOverrides._id || 'one';
|
||||
busytimeOverrides = busytimeOverrides || {};
|
||||
|
||||
setup(function(done) {
|
||||
var storeFactory = core.storeFactory;
|
||||
var busytimeStore = storeFactory.get('Busytime');
|
||||
var eventStore = storeFactory.get('Event');
|
||||
var trans = core.db.transaction(eventStore._dependentStores, 'readwrite');
|
||||
trans.oncomplete = () => done();
|
||||
trans.onerror = event => done(event.target.error);
|
||||
|
||||
eventOverrides.calendarId = this.calendar._id;
|
||||
var event = this.event = Factory('event', eventOverrides);
|
||||
busytimeOverrides.calendarId = this.calendar._id;
|
||||
busytimeOverrides.eventId = this.event._id || eventOverrides._id;
|
||||
var busytime = this.busytime = Factory('busytime', busytimeOverrides);
|
||||
eventStore.persist(event, trans);
|
||||
busytimeStore.persist(busytime, trans);
|
||||
});
|
||||
};
|
||||
|
||||
exports.dbFixtures = function(factory, storeName, list) {
|
||||
var object = Object.create(null);
|
||||
|
||||
setup(function(done) {
|
||||
var db = core.db;
|
||||
var store = core.storeFactory.get(storeName);
|
||||
var trans = db.transaction(store._dependentStores, 'readwrite');
|
||||
trans.oncomplete = () => done();
|
||||
trans.onerror = event => done(event.target.error);
|
||||
|
||||
for (var key in list) {
|
||||
store.persist(
|
||||
(object[key] = Factory(factory, list[key])),
|
||||
trans
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
exports.clearStore = function(db, name, callback) {
|
||||
if (typeof(name) === 'function') {
|
||||
callback = name;
|
||||
name = Object.keys(Db.prototype.store);
|
||||
}
|
||||
|
||||
var trans = db.transaction(name, 'readwrite');
|
||||
trans.oncomplete = () => callback();
|
||||
trans.onerror = () => callback(new Error('Could not wipe accounts db'));
|
||||
|
||||
name = [].concat(name);
|
||||
name.forEach(storeName => {
|
||||
var store = trans.objectStore(storeName);
|
||||
store.clear();
|
||||
});
|
||||
};
|
||||
|
||||
exports.bench = function(iter, cb) {
|
||||
var start = window.performance.now();
|
||||
for (var i = 0; i < iter; i++) {
|
||||
cb();
|
||||
}
|
||||
|
||||
return window.performance.now() - start;
|
||||
};
|
||||
|
||||
exports.vs = function(iter, cmds) {
|
||||
var results = {};
|
||||
for (var key in cmds) {
|
||||
results[key] = exports.bench(iter, cmds[key]);
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.triggerEvent = function(element, eventType) {
|
||||
var event = document.createEvent('HTMLEvents');
|
||||
event.initEvent(eventType, true, true);
|
||||
element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
});
|
||||
10
gaia/apps/calendar/test/unit/support/css.js
Executable file
10
gaia/apps/calendar/test/unit/support/css.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
define(function(require, exports) {
|
||||
'use strict';
|
||||
|
||||
var nextTick = require('common/next_tick');
|
||||
|
||||
exports.load = function(id, require, onLoad) {
|
||||
nextTick(() => onLoad());
|
||||
};
|
||||
|
||||
});
|
||||
12
gaia/apps/calendar/test/unit/support/dom.js
Executable file
12
gaia/apps/calendar/test/unit/support/dom.js
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
/* global requireElements */
|
||||
define(function(require, exports) {
|
||||
'use strict';
|
||||
|
||||
var nextTick = require('common/next_tick');
|
||||
|
||||
exports.load = function(id, require, onLoad) {
|
||||
requireElements('calendar/elements/' + id + '.html');
|
||||
nextTick(() => onLoad());
|
||||
};
|
||||
|
||||
});
|
||||
232
gaia/apps/calendar/test/unit/support/factories/all.js
Executable file
232
gaia/apps/calendar/test/unit/support/factories/all.js
Executable file
|
|
@ -0,0 +1,232 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
var AccountModel = require('models/account');
|
||||
var CalendarModel = require('models/calendar');
|
||||
var Caldav = require('ext/caldav');
|
||||
var Calc = require('common/calc');
|
||||
var Factory = require('test/support/factory');
|
||||
|
||||
/**
|
||||
* Module state
|
||||
*/
|
||||
var calendarId = 0;
|
||||
|
||||
function handleTransportDate(obj) {
|
||||
// handle case of incoming start date
|
||||
if (obj.startDate) {
|
||||
obj.start = Calc.dateToTransport(obj.startDate);
|
||||
}
|
||||
|
||||
if (obj.endDate) {
|
||||
obj.end = Calc.dateToTransport(obj.endDate);
|
||||
}
|
||||
|
||||
// handle case of defaults
|
||||
|
||||
if (!obj.start) {
|
||||
obj.start = Calc.dateToTransport(
|
||||
new Date()
|
||||
);
|
||||
}
|
||||
|
||||
if (obj.start) {
|
||||
obj.startDate = Calc.dateFromTransport(obj.start);
|
||||
}
|
||||
|
||||
if (!obj.end) {
|
||||
obj.end = Calc.dateToTransport(
|
||||
// 1 hour after start
|
||||
new Date(obj.startDate.getTime() + 3600 * 1000)
|
||||
);
|
||||
}
|
||||
|
||||
if (obj.end) {
|
||||
obj.endDate = Calc.dateFromTransport(obj.end);
|
||||
}
|
||||
}
|
||||
|
||||
Factory.define('remote.calendar', {
|
||||
properties: {
|
||||
id: '',
|
||||
url: '/',
|
||||
name: 'my calendar',
|
||||
color: '#333',
|
||||
description: 'description',
|
||||
syncToken: '1',
|
||||
// read, write, delete
|
||||
privilegeSet: ['read', 'write-content', 'unbind']
|
||||
},
|
||||
|
||||
onbuild: function(obj) {
|
||||
var id = obj.id;
|
||||
if (!id) {
|
||||
id = obj.id = 'cuuid/' + calendarId++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var eventId = 0;
|
||||
|
||||
Factory.define('remote.event', {
|
||||
properties: {
|
||||
location: 'location',
|
||||
isRecurring: false,
|
||||
alarms: [
|
||||
{action: 'DISPLAY', trigger: 60000}
|
||||
]
|
||||
//XXX: raw data
|
||||
},
|
||||
|
||||
onbuild: function(obj) {
|
||||
var id = obj.id;
|
||||
if (!id) {
|
||||
id = obj.id = 'euuid/' + eventId++;
|
||||
}
|
||||
|
||||
handleTransportDate(obj);
|
||||
|
||||
if (!obj.title) {
|
||||
obj.title = 'title ' + id;
|
||||
}
|
||||
|
||||
if (!obj.description) {
|
||||
obj.description = 'description ' + id;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('caldav.calendar', {
|
||||
|
||||
get object() {
|
||||
return Caldav.Resources.Calendar;
|
||||
},
|
||||
|
||||
properties: {
|
||||
url: '/cal',
|
||||
name: 'name',
|
||||
color: '#333',
|
||||
ctag: 'token',
|
||||
description: '1',
|
||||
privilegeSet: [
|
||||
'read',
|
||||
'write',
|
||||
'write-content'
|
||||
]
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Factory.define('caldav.account', {
|
||||
properties: {
|
||||
user: 'user',
|
||||
password: 'password',
|
||||
domain: 'http://google.com',
|
||||
entrypoint: '/dav/',
|
||||
calendarHome: '/dav/my/foobar'
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('caldav.connection', {
|
||||
extend: 'caldav.account',
|
||||
|
||||
get object() {
|
||||
return Caldav.Connection;
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('account', {
|
||||
|
||||
get object() {
|
||||
return AccountModel;
|
||||
},
|
||||
|
||||
properties: {
|
||||
providerType: 'Local',
|
||||
user: 'user',
|
||||
password: 'password',
|
||||
domain: 'http://google.com',
|
||||
entrypoint: '/',
|
||||
preset: 'local'
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('calendar', {
|
||||
get object() {
|
||||
return CalendarModel;
|
||||
},
|
||||
|
||||
properties: {
|
||||
accountId: 1,
|
||||
remote: Factory.get('remote.calendar')
|
||||
},
|
||||
|
||||
oncreate: function(obj) {
|
||||
if (!obj._id) {
|
||||
obj._id = obj.accountId + '-' + obj.remote.id;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Factory.define('event', {
|
||||
properties: {
|
||||
calendarId: 1,
|
||||
remote: Factory.get('remote.event')
|
||||
},
|
||||
|
||||
oncreate: function(obj) {
|
||||
if (!obj._id) {
|
||||
obj._id = obj.calendarId + '-' + obj.remote.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var busytimeId = 0;
|
||||
|
||||
Factory.define('busytime', {
|
||||
properties: {
|
||||
calendarId: 'calendar-1',
|
||||
eventId: 'event-1'
|
||||
},
|
||||
|
||||
oncreate: function(obj) {
|
||||
if (!obj._id) {
|
||||
obj._id = obj.eventId + '-' + (++busytimeId);
|
||||
}
|
||||
|
||||
handleTransportDate(obj);
|
||||
|
||||
if (obj.endDate === obj.startDate) {
|
||||
obj.endDate.setHours(obj.endDate.getHours() + 2);
|
||||
handleTransportDate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Factory.define('alarm', {
|
||||
oncreate: function(obj) {
|
||||
if (obj.startDate && obj.startDate instanceof Date) {
|
||||
obj.startDate = Calc.dateToTransport(obj.startDate);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('icalComponent', {
|
||||
oncreate: function(obj) {
|
||||
if (obj.lastRecurrenceId && obj.lastRecurrenceId instanceof Date) {
|
||||
obj.lastRecurrenceId = Calc.dateToTransport(obj.lastRecurrenceId);
|
||||
}
|
||||
},
|
||||
|
||||
properties: {
|
||||
ical: 'fooo!'
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
209
gaia/apps/calendar/test/unit/support/factory.js
Executable file
209
gaia/apps/calendar/test/unit/support/factory.js
Executable file
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* Test factory builder. Inspired by FactoryGirl (of ruby/rails fame).
|
||||
* Tries very hard to respect getters in js objects
|
||||
* as a result there is a performance hit so factories
|
||||
* should not be used when building thousands of objects
|
||||
* but should be fine for the 10-100 objects in small-large
|
||||
* tests.
|
||||
*/
|
||||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
function propIsFactory(object, key) {
|
||||
var descriptor = Object.getOwnPropertyDescriptor(
|
||||
object, key
|
||||
);
|
||||
|
||||
if (!descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
descriptor.value &&
|
||||
(descriptor.value instanceof Factory)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a set of property descriptors from
|
||||
* one object to another
|
||||
*/
|
||||
function copyProp(from, keys, to) {
|
||||
var list = [].concat(keys);
|
||||
list.forEach(function(key) {
|
||||
if (!from.hasOwnProperty(key)) {
|
||||
return;
|
||||
}
|
||||
Object.defineProperty(
|
||||
to,
|
||||
key,
|
||||
Object.getOwnPropertyDescriptor(
|
||||
from,
|
||||
key
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all properties
|
||||
* (in order from left to right to the final argument)
|
||||
*/
|
||||
function copy() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var target = args.pop();
|
||||
|
||||
args.forEach(function(object) {
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
Object.defineProperty(
|
||||
target,
|
||||
key,
|
||||
Object.getOwnPropertyDescriptor(
|
||||
object,
|
||||
key
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/* static api */
|
||||
|
||||
Factory._defined = Object.create(null);
|
||||
|
||||
Factory.get = function(name) {
|
||||
return Factory._defined[name];
|
||||
};
|
||||
|
||||
Factory.define = function(name, options) {
|
||||
if (options.extend) {
|
||||
var factory = Factory.get(options.extend);
|
||||
Factory._defined[name] = factory.extend(
|
||||
options
|
||||
);
|
||||
} else {
|
||||
Factory._defined[name] = new Factory(
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
return Factory._defined[name];
|
||||
};
|
||||
|
||||
Factory.create = function(name, opts) {
|
||||
return Factory.get(name).create(opts);
|
||||
};
|
||||
|
||||
Factory.build = function(name, opts) {
|
||||
return Factory.get(name).build(opts);
|
||||
};
|
||||
|
||||
function Factory(options) {
|
||||
if (!(this instanceof Factory)) {
|
||||
return Factory.create.apply(Factory, arguments);
|
||||
}
|
||||
|
||||
copy(options, this);
|
||||
|
||||
return this;
|
||||
}
|
||||
module.exports = Factory;
|
||||
|
||||
Factory.prototype = {
|
||||
parent: null,
|
||||
object: null,
|
||||
properties: {},
|
||||
|
||||
extend: function(options) {
|
||||
var newFactory = {};
|
||||
|
||||
// we need to copy the prop
|
||||
// rather then do an assignment for lazy-est
|
||||
// possible evaluation of properties.
|
||||
copyProp(
|
||||
this,
|
||||
['object', 'onbuild', 'oncreate'],
|
||||
newFactory
|
||||
);
|
||||
|
||||
copy(options, newFactory);
|
||||
|
||||
newFactory.properties = copy(
|
||||
this.properties,
|
||||
newFactory.properties,
|
||||
{}
|
||||
);
|
||||
|
||||
return new Factory(newFactory);
|
||||
},
|
||||
|
||||
build: function(overrides, childFactoryMethod) {
|
||||
if (typeof(overrides) === 'undefined') {
|
||||
overrides = {};
|
||||
}
|
||||
|
||||
if (typeof(childFactoryMethod) === 'undefined') {
|
||||
childFactoryMethod = 'build';
|
||||
}
|
||||
|
||||
|
||||
var defaults = {};
|
||||
var key;
|
||||
var props = this.properties;
|
||||
|
||||
copy(props, overrides, defaults);
|
||||
|
||||
// expand factories
|
||||
var factoryOverrides;
|
||||
|
||||
for (key in defaults) {
|
||||
// when default property is a factory
|
||||
if (propIsFactory(props, key)) {
|
||||
factoryOverrides = undefined;
|
||||
if (!propIsFactory(defaults, key)) {
|
||||
// user overrides defaults
|
||||
factoryOverrides = defaults[key];
|
||||
}
|
||||
defaults[key] = props[key][childFactoryMethod](
|
||||
factoryOverrides
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(this.onbuild) === 'function') {
|
||||
this.onbuild(defaults);
|
||||
}
|
||||
|
||||
return defaults;
|
||||
},
|
||||
|
||||
create: function(overrides) {
|
||||
var result;
|
||||
var constructor = this.object;
|
||||
var attrs = this.build(overrides, 'create');
|
||||
|
||||
if (constructor) {
|
||||
result = new constructor(attrs);
|
||||
} else {
|
||||
result = attrs;
|
||||
}
|
||||
|
||||
if (typeof(this.oncreate) === 'function') {
|
||||
this.oncreate(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
429
gaia/apps/calendar/test/unit/support/factory_test.js
Executable file
429
gaia/apps/calendar/test/unit/support/factory_test.js
Executable file
|
|
@ -0,0 +1,429 @@
|
|||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var Factory = require('test/support/factory');
|
||||
|
||||
suite('factory', function() {
|
||||
var subject;
|
||||
var realDefined;
|
||||
|
||||
setup(function() {
|
||||
realDefined = Factory._defined;
|
||||
Factory._defined = Object.create(null);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Factory._defined = realDefined;
|
||||
});
|
||||
|
||||
function Model(options) {
|
||||
var key;
|
||||
for (key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
this[key] = options[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suite('hooks', function() {
|
||||
setup(function() {
|
||||
subject = new Factory({
|
||||
onbuild: function(obj) {
|
||||
obj.hitBuild = true;
|
||||
},
|
||||
|
||||
oncreate: function(obj) {
|
||||
obj.hitCreate = true;
|
||||
},
|
||||
|
||||
properties: {
|
||||
one: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('create', function() {
|
||||
var out = subject.create();
|
||||
assert.isTrue(out.hitBuild);
|
||||
assert.isTrue(out.hitCreate);
|
||||
});
|
||||
|
||||
test('build', function() {
|
||||
var out = subject.build();
|
||||
assert.isTrue(out.hitBuild);
|
||||
assert.ok(!out.hitCreate);
|
||||
});
|
||||
});
|
||||
|
||||
suite('simple property factory', function() {
|
||||
setup(function() {
|
||||
subject = new Factory({
|
||||
properties: {
|
||||
get one() {
|
||||
return 'cool';
|
||||
},
|
||||
two: 'foo'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('initialization', function() {
|
||||
assert.deepEqual(subject.properties, {
|
||||
one: 'cool',
|
||||
two: 'foo'
|
||||
});
|
||||
});
|
||||
|
||||
test('create - no overrides', function() {
|
||||
var result = subject.create();
|
||||
|
||||
assert.deepEqual(
|
||||
result,
|
||||
subject.properties
|
||||
);
|
||||
});
|
||||
|
||||
test('create - overrides', function() {
|
||||
var result = subject.create(
|
||||
{ one: '1', three: '3' }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
result, {
|
||||
one: '1',
|
||||
two: 'foo',
|
||||
three: '3'
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('with getters', function() {
|
||||
var increment;
|
||||
|
||||
setup(function() {
|
||||
increment = 0;
|
||||
subject = new Factory({
|
||||
properties: {
|
||||
get increment() {
|
||||
return increment++;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('increment getter', function() {
|
||||
subject.create();
|
||||
subject.create();
|
||||
subject.create();
|
||||
|
||||
var result = subject.create();
|
||||
|
||||
// This is probably something
|
||||
// you would not want to do in real
|
||||
// life but it provides that
|
||||
// increments are clean.
|
||||
assert.equal(result.increment, 0);
|
||||
assert.equal(result.increment, 1);
|
||||
assert.equal(result.increment, 2);
|
||||
assert.equal(result.increment, 3);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('with constructors', function() {
|
||||
setup(function() {
|
||||
subject = new Factory({
|
||||
object: Model,
|
||||
properties: {
|
||||
value: 'foo'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('create - no overrides', function() {
|
||||
var result = subject.create();
|
||||
|
||||
assert.instanceOf(result, Model);
|
||||
assert.equal(result.value, 'foo');
|
||||
});
|
||||
|
||||
test('create - with overrides', function() {
|
||||
var result = subject.create(
|
||||
{ value: 'val', other: true }
|
||||
);
|
||||
|
||||
assert.instanceOf(result, Model);
|
||||
assert.equal(result.value, 'val');
|
||||
assert.equal(result.other, true);
|
||||
});
|
||||
|
||||
test('build', function() {
|
||||
var result = subject.build({ val: 1 });
|
||||
assert.isFalse((
|
||||
result instanceof Model
|
||||
));
|
||||
|
||||
assert.equal(result.val, 1);
|
||||
assert.equal(result.value, 'foo');
|
||||
});
|
||||
});
|
||||
|
||||
suite('with factory props', function() {
|
||||
var childFactory;
|
||||
|
||||
setup(function() {
|
||||
childFactory = new Factory({
|
||||
object: Model,
|
||||
properties: {
|
||||
get child() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
subject = new Factory({
|
||||
properties: {
|
||||
parent: 'yes',
|
||||
child: childFactory,
|
||||
inertChild: childFactory
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('create', function() {
|
||||
var result = subject.create({
|
||||
parentVal: 1,
|
||||
child: {
|
||||
otherVal: 1
|
||||
}
|
||||
});
|
||||
|
||||
assert.instanceOf(result.child, Model);
|
||||
assert.instanceOf(result.inertChild, Model);
|
||||
|
||||
assert.equal(result.parent, 'yes');
|
||||
assert.equal(result.parentVal, 1);
|
||||
|
||||
assert.equal(result.inertChild.child, true);
|
||||
assert.equal(result.child.child, true);
|
||||
assert.equal(result.child.otherVal, 1);
|
||||
});
|
||||
|
||||
test('build', function() {
|
||||
var result = subject.build({
|
||||
child: {
|
||||
otherVal: 1
|
||||
}
|
||||
});
|
||||
|
||||
assert.isFalse((
|
||||
result.child instanceof Model
|
||||
));
|
||||
|
||||
|
||||
assert.isFalse((
|
||||
result.inertChild instanceof Model
|
||||
));
|
||||
});
|
||||
|
||||
test('#extend', function() {
|
||||
var sub = subject.extend({
|
||||
object: Model,
|
||||
properties: {
|
||||
foo: 'bar'
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(!subject.properties.foo);
|
||||
|
||||
assert.equal(sub.object, Model);
|
||||
|
||||
var result = sub.create({
|
||||
other: 'fooz'
|
||||
});
|
||||
|
||||
assert.instanceOf(result, Model);
|
||||
|
||||
assert.notEqual(
|
||||
sub.properties,
|
||||
subject.properties
|
||||
);
|
||||
|
||||
assert.equal(result.other, 'fooz');
|
||||
assert.instanceOf(result.child, Model);
|
||||
assert.instanceOf(result.inertChild, Model);
|
||||
assert.equal(result.child.child, true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('static api', function() {
|
||||
|
||||
var defined;
|
||||
|
||||
setup(function() {
|
||||
defined = Factory.define('one', {
|
||||
object: Model,
|
||||
properties: {
|
||||
one: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('#define', function() {
|
||||
assert.instanceOf(defined, Factory);
|
||||
assert.equal(defined.object, Model);
|
||||
assert.deepEqual(
|
||||
defined.properties,
|
||||
{ one: true }
|
||||
);
|
||||
assert.equal(Factory.get('one'), defined);
|
||||
});
|
||||
|
||||
test('#define - /w extend', function() {
|
||||
Factory.define('one.ext', {
|
||||
extend: 'one',
|
||||
properties: {
|
||||
two: false
|
||||
}
|
||||
});
|
||||
|
||||
assert.instanceOf(
|
||||
Factory.get('one.ext'),
|
||||
Factory
|
||||
);
|
||||
|
||||
var created = Factory.create('one.ext');
|
||||
|
||||
assert.equal(created.one, true);
|
||||
assert.equal(created.two, false);
|
||||
});
|
||||
|
||||
test('#create', function() {
|
||||
var result = Factory.create('one', {
|
||||
extra: true
|
||||
});
|
||||
|
||||
assert.instanceOf(result, Model);
|
||||
assert.equal(result.extra, true);
|
||||
assert.equal(result.one, true);
|
||||
});
|
||||
|
||||
test('#build', function() {
|
||||
var result = Factory.build('one', {
|
||||
extra: true
|
||||
});
|
||||
|
||||
assert.isFalse((
|
||||
result instanceof Model
|
||||
));
|
||||
|
||||
assert.equal(result.extra, true);
|
||||
assert.equal(result.one, true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('acceptance', function() {
|
||||
var result;
|
||||
|
||||
function Event() { Model.apply(this, arguments); }
|
||||
function Cal() { Model.apply(this, arguments); }
|
||||
function Account() { Model.apply(this, arguments); }
|
||||
|
||||
setup(function() {
|
||||
Factory.define('event', {
|
||||
object: Event,
|
||||
properties: {
|
||||
isEvent: true
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('calendar', {
|
||||
object: Cal,
|
||||
properties: {
|
||||
isCalendar: true,
|
||||
event: Factory.get('event')
|
||||
}
|
||||
});
|
||||
|
||||
Factory.define('account', {
|
||||
object: Account,
|
||||
properties: {
|
||||
isAccount: true,
|
||||
normalCal: Factory.get('calendar'),
|
||||
extendCal: Factory.get('calendar').extend({
|
||||
properties: {
|
||||
isCrazy: true,
|
||||
event: Factory.get('event').extend({
|
||||
properties: {
|
||||
isCrazy: true
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function hasProps() {
|
||||
// account
|
||||
assert.isTrue(result.isAccount);
|
||||
|
||||
// normal cal
|
||||
assert.isTrue(result.normalCal.isCalendar);
|
||||
assert.ok(!result.normalCal.isCrazy);
|
||||
|
||||
// crazy cal
|
||||
assert.isTrue(result.extendCal.isCrazy);
|
||||
assert.isTrue(result.extendCal.isCalendar);
|
||||
|
||||
// normal event
|
||||
assert.isTrue(result.normalCal.event.isEvent);
|
||||
assert.ok(!result.normalCal.event.isCrazy);
|
||||
|
||||
// crazy calendar
|
||||
assert.isTrue(result.extendCal.event.isEvent);
|
||||
assert.isTrue(result.extendCal.event.isCrazy);
|
||||
}
|
||||
|
||||
test('#create - no overrides', function() {
|
||||
result = Factory.create('account');
|
||||
|
||||
assert.instanceOf(result, Account, 'result Account');
|
||||
assert.instanceOf(result.normalCal, Cal, 'normalCal');
|
||||
assert.instanceOf(result.extendCal, Cal, 'extendCal');
|
||||
assert.instanceOf(result.normalCal.event, Event, 'normalCal.event');
|
||||
assert.instanceOf(result.extendCal.event, Event, 'extendCal.event');
|
||||
|
||||
hasProps();
|
||||
});
|
||||
|
||||
test('#build - no overrides', function() {
|
||||
result = Factory.build('account');
|
||||
assert.isFalse(
|
||||
result instanceof Account
|
||||
);
|
||||
hasProps();
|
||||
});
|
||||
|
||||
test('deep overrides', function() {
|
||||
result = Factory('account', {
|
||||
normalCal: {
|
||||
foo: true,
|
||||
event: {
|
||||
nested: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// we did not kill the defaults
|
||||
hasProps();
|
||||
|
||||
assert.isTrue(result.normalCal.foo);
|
||||
assert.isTrue(result.normalCal.event.nested);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
23
gaia/apps/calendar/test/unit/support/fake_page.js
Executable file
23
gaia/apps/calendar/test/unit/support/fake_page.js
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
function page() {
|
||||
page.routes.push(Array.prototype.slice.call(arguments));
|
||||
}
|
||||
module.exports = page;
|
||||
|
||||
page.routes = [];
|
||||
|
||||
page.show = function(item) {
|
||||
this.shown = item;
|
||||
};
|
||||
|
||||
page.start = function() {
|
||||
this.started = true;
|
||||
};
|
||||
|
||||
page.stop = function() {
|
||||
this.started = false;
|
||||
};
|
||||
|
||||
});
|
||||
28
gaia/apps/calendar/test/unit/support/mocha_promise.js
Executable file
28
gaia/apps/calendar/test/unit/support/mocha_promise.js
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
module.exports = function mochaPromise(mochaFn, description, callback) {
|
||||
if (typeof description === 'function') {
|
||||
callback = description;
|
||||
description = null;
|
||||
}
|
||||
|
||||
function execute(done) {
|
||||
var promise;
|
||||
try {
|
||||
promise = callback.call();
|
||||
} catch (error) {
|
||||
return done(error);
|
||||
}
|
||||
|
||||
promise.then(() => done()).catch(done);
|
||||
}
|
||||
|
||||
if (description) {
|
||||
mochaFn(description, execute);
|
||||
} else {
|
||||
mochaFn(execute);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
54
gaia/apps/calendar/test/unit/support/mock_alarms.js
Executable file
54
gaia/apps/calendar/test/unit/support/mock_alarms.js
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
define(function(require, exports) {
|
||||
'use strict';
|
||||
|
||||
var _id = 0;
|
||||
var alarms = [];
|
||||
var mozAlarms;
|
||||
|
||||
exports.setup = function() {
|
||||
mozAlarms = navigator.mozAlarms;
|
||||
navigator.mozAlarms = exports;
|
||||
};
|
||||
|
||||
exports.teardown = function() {
|
||||
removeAll();
|
||||
navigator.mozAlarms = mozAlarms;
|
||||
};
|
||||
|
||||
exports.add = function(date, honorTimezone, data) {
|
||||
var alarmId = _id++;
|
||||
alarms.push({
|
||||
alarmId: alarmId,
|
||||
date: date,
|
||||
honorTimezone: honorTimezone,
|
||||
data: data
|
||||
});
|
||||
|
||||
return resolve(alarmId);
|
||||
};
|
||||
|
||||
exports.getAll = function() {
|
||||
return resolve(alarms);
|
||||
};
|
||||
|
||||
exports.remove = function(alarmId) {
|
||||
alarms = alarms.filter(alarm => alarm.alarmId !== alarmId);
|
||||
};
|
||||
|
||||
function removeAll() {
|
||||
alarms = [];
|
||||
}
|
||||
|
||||
function resolve(result) {
|
||||
var request = { onsuccess: null, onerror: null };
|
||||
var requestContext = {};
|
||||
requestContext.result = result;
|
||||
setTimeout(() => {
|
||||
return request.onsuccess &&
|
||||
request.onsuccess.call(requestContext, result);
|
||||
}, 10);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
});
|
||||
213
gaia/apps/calendar/test/unit/support/mock_provider.js
Executable file
213
gaia/apps/calendar/test/unit/support/mock_provider.js
Executable file
|
|
@ -0,0 +1,213 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
var Parent = require('provider/abstract');
|
||||
var nextTick = require('common/next_tick');
|
||||
|
||||
function accountGeneric(mockName) {
|
||||
return function(account, callback) {
|
||||
// next tick is scheduled before _resolveStage intentionally
|
||||
nextTick(function() {
|
||||
callback.apply(
|
||||
null,
|
||||
this._resolveStaged(mockName, account) || [null, {}]
|
||||
);
|
||||
}.bind(this));
|
||||
};
|
||||
}
|
||||
|
||||
function accountStaging(mockName) {
|
||||
return function() {
|
||||
var args = Array.slice(arguments);
|
||||
var user = args.shift();
|
||||
|
||||
function matcher(object) {
|
||||
return object.user === user;
|
||||
}
|
||||
|
||||
return this._stage(mockName, matcher, args);
|
||||
};
|
||||
}
|
||||
|
||||
var stageEvents = {
|
||||
onbefore: function() {},
|
||||
onafter: function() {}
|
||||
};
|
||||
|
||||
function Mock() {
|
||||
Parent.apply(this, arguments);
|
||||
|
||||
// mock call storage
|
||||
this._stageObjects = Object.create(null);
|
||||
}
|
||||
module.exports = Mock;
|
||||
|
||||
Mock.prototype = {
|
||||
__proto__: Parent.prototype,
|
||||
|
||||
// opt-into sync by default
|
||||
canSync: true,
|
||||
|
||||
_stage: function(name, matcher, args) {
|
||||
if (!(this._stageObjects[name])) {
|
||||
this._stageObjects[name] = [];
|
||||
}
|
||||
|
||||
var handler = Object.create(stageEvents);
|
||||
|
||||
this._stageObjects[name].push({
|
||||
matches: matcher,
|
||||
args: args,
|
||||
handler: handler
|
||||
});
|
||||
|
||||
return handler;
|
||||
},
|
||||
|
||||
/**
|
||||
* Used to find staged objects.
|
||||
* The found object must be saved as
|
||||
* this method will also remove any found item.
|
||||
*
|
||||
* Stops at first found item that matches condition.
|
||||
*
|
||||
* var stagedValue = this._resolveStaged('type', input) || someDefault;
|
||||
*
|
||||
*/
|
||||
_resolveStaged: function(name, input) {
|
||||
var list = this._stageObjects[name];
|
||||
if (!list) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var len = list.length;
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (list[i].matches(input)) {
|
||||
// remove and return args
|
||||
var item = list.splice(i, 1)[0];
|
||||
var args = item.args;
|
||||
var handler = item.handler;
|
||||
|
||||
handler.onbefore(args);
|
||||
nextTick(handler.onafter.bind(null, args));
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stage a getAccount call.
|
||||
*
|
||||
* @param {String} user name to stage information for.
|
||||
* @param {Object|Null} err given to callback.
|
||||
* @param {Object|Null} object given to callback.
|
||||
*/
|
||||
stageGetAccount: accountStaging('getAccount'),
|
||||
stageFindCalendars: accountStaging('findCalendars'),
|
||||
|
||||
stageSyncEvents: function(user, calendarRemoteId, err) {
|
||||
err = err || null;
|
||||
|
||||
function matcher(args) {
|
||||
return (
|
||||
args[0].user === user &&
|
||||
args[1].remote.id === calendarRemoteId
|
||||
);
|
||||
}
|
||||
|
||||
return this._stage('syncEvents', matcher, err);
|
||||
},
|
||||
|
||||
stageEventCapabilities: function() {
|
||||
var args = Array.slice(arguments);
|
||||
var id = args.shift();
|
||||
|
||||
function matcher(event) {
|
||||
return event._id === id;
|
||||
}
|
||||
|
||||
return this._stage('eventCapabilities', matcher, args);
|
||||
},
|
||||
|
||||
stageCalendarCapabilities: function() {
|
||||
var args = Array.slice(arguments);
|
||||
var id = args.shift();
|
||||
|
||||
function matcher(calendar) {
|
||||
return calendar._id === id;
|
||||
}
|
||||
|
||||
return this._stage('calendarCapabilities', matcher, args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stage findCalendars call.
|
||||
*
|
||||
*
|
||||
* provider.stageFindCalendars(
|
||||
* accountModel.user,
|
||||
* err || null,
|
||||
* {
|
||||
* remoteId: { id: 'remoteId', ... },
|
||||
* ...
|
||||
* }
|
||||
* );
|
||||
*/
|
||||
findCalendars: accountGeneric('findCalendars'),
|
||||
|
||||
getAccount: accountGeneric('getAccount'),
|
||||
|
||||
syncEvents: function(account, calendar, callback) {
|
||||
// first so this tick is scheduled first
|
||||
nextTick(function() {
|
||||
callback(
|
||||
this._resolveStaged('syncEvents', [account, calendar])
|
||||
);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
calendarCapabilities: function(calendar) {
|
||||
var defaults = {
|
||||
canUpdateEvent: true,
|
||||
canCreateEvent: true,
|
||||
canDeleteEvent: true
|
||||
};
|
||||
|
||||
var args =
|
||||
this._resolveStaged('calendarCapabilities', calendar) || [];
|
||||
|
||||
var overrides = args[0] || {};
|
||||
|
||||
for (var key in overrides) {
|
||||
defaults[key] = overrides[key];
|
||||
}
|
||||
|
||||
return defaults;
|
||||
},
|
||||
|
||||
eventCapabilities: function(event, callback) {
|
||||
var defaults = {
|
||||
canUpdate: true,
|
||||
canCreate: true,
|
||||
canDelete: true
|
||||
};
|
||||
|
||||
nextTick(function() {
|
||||
var args = this._resolveStaged('eventCapabilities', event) || [];
|
||||
var err = args[0] || null;
|
||||
var overrides = args[1] || {};
|
||||
|
||||
for (var key in overrides) {
|
||||
defaults[key] = overrides[key];
|
||||
}
|
||||
|
||||
callback(err, defaults);
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
33
gaia/apps/calendar/test/unit/support/mock_request_wake_lock.js
Executable file
33
gaia/apps/calendar/test/unit/support/mock_request_wake_lock.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
define(function(require, exports) {
|
||||
'use strict';
|
||||
|
||||
var requestWakeLock;
|
||||
|
||||
exports.setup = function() {
|
||||
requestWakeLock = navigator.requestWakeLock;
|
||||
navigator.requestWakeLock = fakeRequestWakeLock;
|
||||
};
|
||||
|
||||
exports.teardown = function() {
|
||||
navigator.requestWakeLock = requestWakeLock;
|
||||
locks = exports.locks = [];
|
||||
};
|
||||
|
||||
var locks = exports.locks = [];
|
||||
function fakeRequestWakeLock(type) {
|
||||
var lock = createFakeLock(type);
|
||||
locks.push(lock);
|
||||
return lock;
|
||||
}
|
||||
|
||||
function createFakeLock(type) {
|
||||
return {
|
||||
type: type,
|
||||
unlocked: false,
|
||||
unlock: function() {
|
||||
this.unlocked = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
33
gaia/apps/calendar/test/unit/support/mock_view.js
Executable file
33
gaia/apps/calendar/test/unit/support/mock_view.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
function View(options) {
|
||||
var self = this;
|
||||
var key;
|
||||
|
||||
if (typeof(options) === 'undefined') {
|
||||
options = {};
|
||||
}
|
||||
|
||||
for (key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
this[key] = options[key];
|
||||
}
|
||||
}
|
||||
|
||||
this.called = 1;
|
||||
this.args = arguments;
|
||||
|
||||
this.onactive = function() {
|
||||
self.activeWith = arguments;
|
||||
self.active = true;
|
||||
};
|
||||
|
||||
this.oninactive = function() {
|
||||
self.inactiveWith = arguments;
|
||||
self.active = false;
|
||||
};
|
||||
}
|
||||
module.exports = View;
|
||||
|
||||
});
|
||||
17
gaia/apps/calendar/test/unit/support/suite_group.js
Executable file
17
gaia/apps/calendar/test/unit/support/suite_group.js
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
/** Deprecated! */
|
||||
module.exports = function(name, callback) {
|
||||
suite(name, function() {
|
||||
suiteSetup(function(done) {
|
||||
require([name], function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
93
gaia/apps/calendar/test/unit/support/test_loader.js
Executable file
93
gaia/apps/calendar/test/unit/support/test_loader.js
Executable file
|
|
@ -0,0 +1,93 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
var asyncRequire = require('common/async_require');
|
||||
var chai = require('ext/chai');
|
||||
var chaiAsPromised = require('ext/chai-as-promised');
|
||||
var co = require('ext/co');
|
||||
|
||||
module.exports = function testLoader(path) {
|
||||
return co(function *() {
|
||||
console.log(`Will load test ${path}`);
|
||||
l10nLink('/locales/calendar.{locale}.properties');
|
||||
l10nLink('/shared/locales/date/date.{locale}.properties');
|
||||
l10nMeta('en-US', ['en-US']);
|
||||
yield loadL10n();
|
||||
var testSupport = yield asyncRequire('test/support/calendar');
|
||||
testSupport.core();
|
||||
// TODO(gaye): No more window/global stuff...
|
||||
window.testSupport = window.testSupport || {};
|
||||
window.testSupport.calendar = testSupport;
|
||||
chai.use(chaiAsPromised);
|
||||
extendChai();
|
||||
window.assert = chai.assert;
|
||||
window.expect = chai.expect;
|
||||
window.should = chai.Should();
|
||||
yield asyncRequire(path);
|
||||
});
|
||||
};
|
||||
|
||||
function *loadL10n() {
|
||||
yield asyncRequire('shared/l10n');
|
||||
|
||||
// Massive hack to trick l10n to load
|
||||
// TODO: upstream a fix to l10n.js
|
||||
document.dispatchEvent(new Event('DOMContentLoaded'));
|
||||
|
||||
var readyState = navigator.mozL10n.readyState;
|
||||
switch (readyState) {
|
||||
case 'complete':
|
||||
case 'interactive':
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise(resolve => window.addEventListener('localized', resolve));
|
||||
}
|
||||
|
||||
function l10nLink(href) {
|
||||
var link = document.createElement('link');
|
||||
link.setAttribute('href', href);
|
||||
link.setAttribute('rel', 'localization');
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function l10nMeta(defaultLanguage, availableLanguages) {
|
||||
var metaDL = document.createElement('meta');
|
||||
metaDL.setAttribute('name', 'defaultLanguage');
|
||||
metaDL.setAttribute('content', defaultLanguage);
|
||||
|
||||
var metaAL = document.createElement('meta');
|
||||
metaAL.setAttribute('name', 'availableLanguages');
|
||||
metaAL.setAttribute('content', availableLanguages.join(', '));
|
||||
|
||||
document.head.appendChild(metaDL);
|
||||
document.head.appendChild(metaAL);
|
||||
}
|
||||
|
||||
function extendChai() {
|
||||
// XXX: this is a lame way to do this
|
||||
// in reality we need to fix the above upstream
|
||||
// and leverage new chai 1x methods
|
||||
chai.assert.hasProperties = function(given, props, msg) {
|
||||
msg = (typeof(msg) === 'undefined') ? '' : msg + ': ';
|
||||
|
||||
if (props instanceof Array) {
|
||||
props.forEach(function(prop) {
|
||||
assert.ok(
|
||||
(prop in given),
|
||||
msg + 'given should have "' + prop + '" property'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
for (var key in props) {
|
||||
assert.deepEqual(
|
||||
given[key],
|
||||
props[key],
|
||||
msg + ' property equality for (' + key + ') '
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
17
gaia/apps/calendar/test/unit/support/wait_for.js
Executable file
17
gaia/apps/calendar/test/unit/support/wait_for.js
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
var denodeify = require('common/promise').denodeify;
|
||||
|
||||
function waitFor(test, callback) {
|
||||
var result = test();
|
||||
if (result) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
setTimeout(() => waitFor(test, callback), 200);
|
||||
}
|
||||
|
||||
module.exports = denodeify(waitFor);
|
||||
|
||||
});
|
||||
Loading…
Reference in a new issue