diff options
author | James Lal <james@lightsofapollo.com> | 2012-06-27 11:31:51 +0200 |
---|---|---|
committer | James Lal <james@lightsofapollo.com> | 2012-06-27 11:31:51 +0200 |
commit | c3db57754c540129bd004137ab88be69788217d2 (patch) | |
tree | 758acbd7c7fcb42f392838a55125d090697a336c | |
parent | 95d50ef280c46ce6a29454285ccd7fc42cbcac61 (diff) | |
download | jsCalDAV-c3db57754c540129bd004137ab88be69788217d2.tar.gz |
Add calendar data / calendar query
-rw-r--r-- | lib/webcals/request/calendar_query.js | 31 | ||||
-rw-r--r-- | lib/webcals/templates/calendar_data.js | 93 | ||||
-rw-r--r-- | test/webcals/request/calendar_query_test.js | 104 | ||||
-rw-r--r-- | test/webcals/templates/calendar_data_test.js | 65 |
4 files changed, 293 insertions, 0 deletions
diff --git a/lib/webcals/request/calendar_query.js b/lib/webcals/request/calendar_query.js new file mode 100644 index 0000000..b25a1c1 --- /dev/null +++ b/lib/webcals/request/calendar_query.js @@ -0,0 +1,31 @@ +(function(module, ns) { + + var Propfind = ns.require('request/propfind'); + + /** + * Creates a calendar query request. + * + * Defaults to Depth of 1. + * + * @param {String} url location to make request. + * @param {Object} options options for calendar query. + */ + function CalendarQuery(url, options) { + Propfind.apply(this, arguments); + + this.xhr.headers['Depth'] = this.depth || 1; + this.xhr.method = 'REPORT'; + } + + CalendarQuery.prototype = { + __proto__: Propfind.prototype + }; + + module.exports = CalendarQuery; + +}.apply( + this, + (this.Webcals) ? + [Webcals('request/calendar_query'), Webcals] : + [module, require('../webcals')] +)); diff --git a/lib/webcals/templates/calendar_data.js b/lib/webcals/templates/calendar_data.js new file mode 100644 index 0000000..9ff2a1e --- /dev/null +++ b/lib/webcals/templates/calendar_data.js @@ -0,0 +1,93 @@ +(function(module, ns) { + + function CalendarData() { + this.struct = {}; + } + + CalendarData.prototype = { + + /** + * Appends a list of fields + * to a given iCalendar field set. + * + * @param {String} type iCal fieldset (VTODO, VEVENT,...). + */ + select: function(type, list) { + var struct = this.struct; + + if (!(type in struct)) { + struct[type] = []; + } + + struct[type] = struct[type].concat(list); + + return this; + }, + + /** + * Accepts an object full of arrays + * recuse when encountering another object. + */ + _renderFieldset: function(template, element) { + var tag; + var value; + var i; + var output = ''; + var elementOutput = ''; + + for (tag in element) { + value = element[tag]; + for (i = 0; i < value.length; i++) { + if (typeof(value[i]) === 'object') { + elementOutput += this._renderFieldset( + template, + value[i] + ); + } else { + elementOutput += template.tag( + ['caldav', 'prop'], + { name: value[i] } + ); + } + } + output += template.tag( + ['caldav', 'comp'], + { name: tag }, + elementOutput + ); + elementOutput = ''; + } + + return output; + }, + + /** + * Renders CalendarData with a template. + * + * @param {WebCals.Template} template calendar to render. + * @return {String} <calendardata /> xml output. + */ + render: function(template) { + var struct = this.struct; + var output = template.tag( + ['caldav', 'calendar-data'], + template.tag( + ['caldav', 'comp'], + { name: 'VCALENDAR' }, + this._renderFieldset(template, struct) + ) + ); + + return output; + } + }; + + + module.exports = CalendarData; + +}.apply( + this, + (this.Webcals) ? + [Webcals('templates/calendar_data'), Webcals] : + [module, require('../webcals')] +)); diff --git a/test/webcals/request/calendar_query_test.js b/test/webcals/request/calendar_query_test.js new file mode 100644 index 0000000..803b09a --- /dev/null +++ b/test/webcals/request/calendar_query_test.js @@ -0,0 +1,104 @@ +requireRequest(); +requireLib('request/propfind'); +requireLib('request/calendar_query'); + +suite('webcals/request/propfind', function() { + var Abstract, + Propfind, + FakeXhr, + CalendarQuery, + Xhr, + Template, + oldXhrClass, + SaxResponse; + + var url = 'http://google.com', + subject; + + suiteSetup(function() { + Propfind = Webcals.require('request/propfind'); + CalendarQuery = Webcals.require('request/calendar_query'); + SaxResponse = Webcals.require('sax/dav_response'); + FakeXhr = Webcals.require('support/fake_xhr'); + Template = Webcals.require('template'); + Xhr = Webcals.require('xhr'); + + oldXhrClass = Xhr.prototype.xhrClass; + Xhr.prototype.xhrClass = FakeXhr; + }); + + suiteTeardown(function() { + Xhr.prototype.xhrClass = oldXhrClass; + }); + + setup(function() { + subject = new CalendarQuery(url); + FakeXhr.instances.length = 0; + }); + + test('initializer', function() { + assert.instanceOf(subject, Propfind); + assert.deepEqual(subject._props, []); + assert.equal(subject.xhr.headers['Depth'], 1); + assert.equal(subject.xhr.method, 'REPORT'); + }); + + test('#prop', function() { + var expected = subject.template.tag('test'); + + subject.prop('test'); + + assert.deepEqual(subject._props, [expected]); + }); + + test('#_createPayload', function() { + return; + subject.prop('foo'); + subject.prop('bar'); + + var tags = [ + '<N0:foo />', + '<N0:bar />' + ].join(''); + + var expected = [ + subject.template.doctype, + '<N0:propfind xmlns:N0="DAV:">', + '<N0:prop>', tags, '</N0:prop>', + '</N0:propfind>' + ].join(''); + + assert.equal(subject._createPayload(), expected); + }); + + suite('integration', function() { + return; + var xml, + data, + result, + xhr, + calledWith; + + defineSample('xml/propget.xml', function(data) { + xml = data; + }); + + setup(function(done) { + subject.prop('foo'); + + subject.send(function(err, tree) { + data = tree; + done(); + }); + + xhr = FakeXhr.instances.pop(); + xhr.respond(xml, 207); + }); + + test('simple tree', function() { + assert.ok(data['/calendar/user/']); + }); + }); + +}); + diff --git a/test/webcals/templates/calendar_data_test.js b/test/webcals/templates/calendar_data_test.js new file mode 100644 index 0000000..5223f18 --- /dev/null +++ b/test/webcals/templates/calendar_data_test.js @@ -0,0 +1,65 @@ +requireRequest(); +requireLib('templates/calendar_data'); + +suite('webcals/templates/calendar_data', function() { + var CalendarData; + var Template; + + var subject; + var template; + + function select() { + subject.select('VTODO', ['DTIME']); + subject.select('VTODO', ['NAME', { VTIMEZONE: true }]); + subject.select('VEVENT', ['NAME', { + 'VALARM': ['NAME'] + }]); + } + + suiteSetup(function() { + CalendarData = Webcals.require('templates/calendar_data'); + Template = Webcals.require('template'); + }); + + setup(function() { + subject = new CalendarData(); + template = new Template('root'); + }); + + test('initialization', function() { + assert.deepEqual(subject.struct, {}); + }); + + suite('#render', function() { + var output; + var expected; + + expected = [ + '<N0:calendar-data>', + '<N0:comp name="VCALENDAR">', + '<N0:comp name="VTODO">', + '<N0:prop name="DTIME" />', + '<N0:prop name="NAME" />', + '<N0:comp name="VTIMEZONE" />', + '</N0:comp>', + '<N0:comp name="VEVENT">', + '<N0:prop name="NAME" />', + '<N0:comp name="VALARM">', + '<N0:prop name="NAME" />', + '</N0:comp>', + '</N0:comp>', + '</N0:comp>', + '</N0:calendar-data>' + ].join(''); + + setup(function() { + select(); + }); + + test('output', function() { + var output = subject.render(template); + assert.equal(output, expected); + }); + }); + +}); |