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:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,101 @@
define(function(require, exports, module) {
'use strict';
var IcalRecurExpansion = require('service/ical_recur_expansion');
function request(file, cb) {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/test/unit/' + file + '?' + Date.now(), true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status !== 200) {
cb(new Error('file not found or other error (' + file + ')', xhr));
} else {
cb(null, xhr.responseText);
}
}
};
xhr.send(null);
}
function camelize(string) {
var out = string.replace(/(?:^|[-_])(\w)/g, function(_, c) {
return c ? c.toUpperCase() : '';
});
return out[0].toLowerCase() + out.slice(1);
}
const ICAL_ROOT = 'fixtures/caldav/ical/';
var Handlers = {
/**
* Load and parse an ical sample
*
* @param {String} file location of ical file.
* @param {Function} node style callback: err, contents.
*/
ical: function icalLoader(file, callback) {
request(ICAL_ROOT + file + '.ics', function(err, text) {
if (err) {
callback(err);
return;
}
callback(null, text);
});
}
};
function Fixtures(type) {
var pending = 0;
var self = this;
var handler = Handlers[type];
function next() {
if (!(--pending)) {
if (self._error) {
throw self._error;
}
self.onready();
}
}
this.load = function loadFixture(file) {
pending++;
handler(file, function(err, contents) {
if (err) {
self._error = err;
} else {
self[camelize(file)] = contents;
}
next();
});
};
return this;
}
var Helper = {
Fixtures: Fixtures,
_originalExpansionLimit: null,
resetExpansionLimit: function() {
if (!Helper._originalExpansionLimit) {
IcalRecurExpansion.forEachLimit = Helper._originalExpansionLimit;
}
},
setExpansionLimit: function(newLimit) {
if (!Helper._originalExpansionLimit) {
Helper._originalExpansionLimit = IcalRecurExpansion.forEachLimit;
}
IcalRecurExpansion.forEachLimit = newLimit;
}
};
module.exports = Helper;
});

View file

@ -0,0 +1,275 @@
define(function(require) {
'use strict';
var CaldavService = require('service/caldav');
var ICAL = require('ext/ical');
var IcalRecurExpansion = require('service/ical_recur_expansion');
var Responder = require('common/responder');
var ServiceSupport = require('test/service/helper');
suite('service/ical_recur_expansion', function() {
var fixtures;
var subject;
var parseEvent;
var forEachLimit = 30;
suiteSetup(function() {
subject = IcalRecurExpansion;
// replace the maximum iterators with a smaller
// number suitable for tests.
ServiceSupport.setExpansionLimit(forEachLimit);
});
suiteTeardown(function() {
ServiceSupport.resetExpansionLimit();
});
// setup fixtures...
suiteSetup(function(done) {
fixtures = new ServiceSupport.Fixtures('ical');
fixtures.load('recurring_event');
fixtures.onready = done;
var service = new CaldavService(new Responder());
parseEvent = service.parseEvent.bind(service);
});
test('initialization', function() {
assert.ok(subject, 'exists');
});
suite('#forEach', function() {
var minDate;
var maxDate;
var inclusiveDates = [];
var iterator;
suiteSetup(function() {
// min will be the 5th date - 1 second
// max will be the 14th + 1 secound
// so 5-15 will be the range we expect.
parseEvent(fixtures.recurringEvent, function(err, event) {
var iter = event.iterator();
var num = 15;
while (--num) {
var last = iter.next();
if (num === 1) {
maxDate = last;
}
if (num === 10) {
minDate = last;
}
if (num <= 10) {
inclusiveDates.push(last.toJSDate());
}
}
minDate.second -= 1;
maxDate.second -= 1;
});
});
// create closed scope for sent/each for re-usability.
var verifyBounds = (function() {
var sent = [];
function each(item) {
sent.push(item.toJSDate());
}
function verifyMinMax() {
test('min & max', function() {
sent.length = 0;
var iter = subject.forEach(
event,
iterator,
each,
minDate,
maxDate
);
assert.deepEqual(
sent,
inclusiveDates
);
assert.deepEqual(
iter.last.toJSDate(),
inclusiveDates[inclusiveDates.length - 1]
);
});
}
function verifyMax() {
test('max', function() {
sent.length = 0;
var iter = subject.forEach(
event,
iterator,
each,
null,
maxDate
);
assert.deepEqual(
iter.last.toJSDate(),
inclusiveDates[inclusiveDates.length - 1],
'has last date'
);
});
}
function verifyMin() {
test('min', function() {
sent.length = 0;
subject.forEach(
event,
iterator,
each,
minDate
);
assert.deepEqual(
sent[0],
inclusiveDates[0]
);
assert.lengthOf(sent, forEachLimit, 'limit bounds');
});
test('min verify exclusive', function() {
sent.length = 0;
var exclusiveMin = minDate.clone();
exclusiveMin.second += 1;
subject.forEach(
event,
iterator,
each,
exclusiveMin
);
assert.deepEqual(
sent[0],
inclusiveDates[1]
);
assert.lengthOf(sent, forEachLimit, 'limit bounds');
});
}
return function verifyBounds() {
suite('bounds', function() {
verifyMax();
verifyMin();
verifyMinMax();
});
};
}());
var event;
setup(function(done) {
parseEvent(fixtures.recurringEvent, function(err, result) {
event = result;
done();
});
});
suite('with a pre-existing iterator', function() {
var last;
setup(function() {
iterator = event.iterator();
iterator.next();
last = iterator.next();
});
test('with a broken iterator', function() {
// round trip the data so we can clone it.
var iterStr = JSON.stringify(iterator);
var iterClone = new ICAL.RecurExpansion(
JSON.parse(iterStr)
);
var expected = [];
subject.forEach(event, iterClone, function(item) {
expected.push(item.toJSDate());
}, minDate, maxDate);
var sent = [];
subject.forEach(event, {}, function(item) {
sent.push(item.toJSDate());
}, minDate, maxDate);
assert.deepEqual(sent, expected);
});
test('resuming iteration', function() {
var expectedIter = event.iterator();
expectedIter.next();
expectedIter.next();
var expected = expectedIter.next();
var sent = [];
iterator = JSON.parse(
JSON.stringify(iterator)
);
subject.forEach(event, iterator, function(item) {
sent.push(item);
});
assert.deepEqual(
sent[0].toJSDate(),
expected.toJSDate()
);
assert.ok(
sent[0].compare(sent[1]) < 0,
'future instances are in the future'
);
});
verifyBounds();
});
suite('without an iterator', function() {
// ensure helpers have no iterators
setup(function() {
iterator = null;
});
test('without timeframe', function() {
var sent = [];
var iter = subject.forEach(event, null, function(last) {
sent.push(last);
});
assert.instanceOf(iter, ICAL.RecurExpansion);
assert.lengthOf(sent, forEachLimit);
// test sanity we need an infinite recur iterator
// or our tests simply suck...
assert.isFalse(iter.complete, 'should be incomplete');
});
verifyBounds();
});
});
});
});