diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | caldav.js | 504 | ||||
-rw-r--r-- | lib/caldav/index.js | 2 | ||||
-rw-r--r-- | lib/caldav/request/calendar_query.js | 24 | ||||
-rw-r--r-- | lib/caldav/templates/calendar_data.js | 115 | ||||
-rw-r--r-- | lib/caldav/templates/calendar_filter.js | 32 | ||||
-rw-r--r-- | lib/caldav/templates/index.js | 13 | ||||
-rw-r--r-- | test/caldav/index_test.js | 14 | ||||
-rw-r--r-- | test/caldav/request/calendar_query_test.js | 22 | ||||
-rw-r--r-- | test/caldav/templates/calendar_data_test.js | 70 | ||||
-rw-r--r-- | test/caldav/templates/calendar_filter_test.js | 53 |
11 files changed, 373 insertions, 480 deletions
@@ -24,10 +24,9 @@ package: test-agent-config cat $(LIB_ROOT)/responder.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax.js >> $(WEB_FILE) cat $(LIB_ROOT)/template.js >> $(WEB_FILE) + cat $(LIB_ROOT)/query_builder.js >> $(WEB_FILE) cat $(LIB_ROOT)/xhr.js >> $(WEB_FILE) cat $(LIB_ROOT)/connection.js >> $(WEB_FILE) - cat $(LIB_ROOT)/templates/calendar_data.js >> $(WEB_FILE) - cat $(LIB_ROOT)/templates/calendar_filter.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax/base.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax/calendar_data_handler.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax/dav_response.js >> $(WEB_FILE) @@ -40,7 +39,6 @@ package: test-agent-config cat $(LIB_ROOT)/request/index.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax/index.js >> $(WEB_FILE) - cat $(LIB_ROOT)/templates/index.js >> $(WEB_FILE) cat $(LIB_ROOT)/resources/calendar.js >> $(WEB_FILE) cat $(LIB_ROOT)/resources/index.js >> $(WEB_FILE) @@ -1662,6 +1662,324 @@ function write (chunk) { @namespace */ (function(module, ns) { + var Template = ns.require('template'); + + /** + * Builds a node of a calendar-data or filter xml element. + * + * @param {QueryBuilder} builder instance. + * @param {String} name component/prop name (like RRULE/VEVENT). + * @param {Boolean} isProp is this node a property tag? + */ + function Node(builder, name, isProp) { + this.name = name; + this.builder = builder; + this.isProp = !!isProp; + + this.comps = Object.create(null); + this.props = Object.create(null); + } + + Node.prototype = { + + /** + * Hook for adding custom node content. + * (for unsupported or custom filters) + * + * Usually you never want to use this. + * + * @type {Null|Array} + */ + content: null, + + /** + * Appends custom string content into node. + * + * @param {String} string content. + */ + appendString: function(string) { + if (!this.content) { + this.content = []; + } + + if (typeof(string) !== 'string') { + string = string.toString(); + } + + this.content.push(string); + }, + + _timeRange: null, + + /** + * Adds a time range element to the node. + * + * Example: + * + * var node; + * + * // key/values not validated or converted + * // but directly piped into the time-range element. + * node.setTimeRange({ + * start: '20060104T000000Z', + * end: '20060105T000000Z' + * }); + * + * // when null removes element + * node.setTimeRange(null); + * + * @param {Object|Null} range time range or null to remove. + */ + setTimeRange: function(range) { + this._timeRange = range; + }, + + /** + * Removes a property from the output. + * @param {String} name prop. + */ + removeProp: function(name) { + delete this.props[name]; + }, + + /** + * Removes a component from the output. + * + * @param {String} name comp. + */ + removeComp: function(name) { + delete this.comps[name]; + }, + + _addNodes: function(type, nodes) { + // return value when is array + var result = this; + + if (!Array.isArray(nodes)) { + // clear out the return value as we will + // now use the first node. + result = null; + } + + nodes = (Array.isArray(nodes)) ? nodes : [nodes]; + + var idx = 0; + var len = nodes.length; + var name; + var node; + + for (; idx < len; idx++) { + name = nodes[idx]; + node = new Node(this.builder, name, type === 'props'); + this[type][name] = node; + } + + // when we where not given an array of nodes + // assume we want one specific one so set that + // as the return value. + if (!result) + result = node; + + return result; + }, + + /** + * Adds one or more props. + * If property already exists will not add + * duplicates but return the existing property. + * + * @param {String|Array[String]} prop one or more properties to add. + * @return {Node|Self} returns a node or self when given an array. + */ + prop: function(prop) { + return this._addNodes('props', prop); + }, + + /** + * Adds one or more comp. + * If comp already exists will not add + * duplicates but return the existing comp. + * + * @param {String|Array[String]} comp one or more components to add. + * @return {Node|Self} returns a node or self when given an array. + */ + comp: function(comp) { + return this._addNodes('comps', comp); + }, + + xmlAttributes: function() { + return { name: this.name }; + }, + + /** + * Transform tree into a string. + * + * NOTE: order is not preserved at all here. + * It is highly unlikely that order is a + * factor for calendar-data or filter + * but this is fair warning for other uses. + */ + toString: function() { + var content = ''; + var key; + var template = this.builder.template; + + if (this._timeRange) { + content += template.tag( + ['caldav', 'time-range'], + this._timeRange + ); + } + + // render out children + for (key in this.props) { + content += this.props[key].toString(); + } + + for (key in this.comps) { + content += this.comps[key].toString(); + } + + if (this.content) { + content += this.content.join(''); + } + + // determine the tag name + var tag; + if (this.isProp) { + tag = this.builder.propTag; + } else { + tag = this.builder.compTag; + } + + // build the xml element and return it. + return template.tag( + tag, + this.xmlAttributes(), + content + ); + } + }; + + /** + * Query builder can be used to build xml document fragments + * for calendar-data & calendar-filter. + * (and any other xml document with a similar structure) + * + * Options: + * - template: (Caldav.Template instance) + * - tag: container tag (like 'calendar-data') + * - attributes: attributes for root + * - compTag: name of comp[onent] tag name (like 'comp') + * - propTag: name of property tag (like 'prop') + * + * @param {Object} options query builder options. + */ + function QueryBuilder(options) { + if (!options) + options = {}; + + if (!(options.template instanceof Template)) { + throw new TypeError( + '.template must be an instance' + + ' of Caldav.Template given "' + options.template + '"' + ); + } + + for (var key in options) { + if (options.hasOwnProperty(key)) { + this[key] = options[key]; + } + } + } + + QueryBuilder.prototype = { + tag: ['caldav', 'calendar-data'], + + compTag: ['caldav', 'comp'], + + propTag: ['caldav', 'prop'], + + attributes: null, + + _limitRecurrenceSet: null, + + /** + * Adds the recurrence set limit child to the query. + * Directly maps to the caldav 'limit-recurrence-set' element. + * + * Examples: + * + * var builder; + * + * // no validation or formatting is done. + * builder.setRecurrenceSetLimit({ + * start: '20060103T000000Z', + * end: '20060103T000000Z' + * }); + * + * // use null to clear value + * builder.setRecurrenceSetLimit(null); + * + * @param {Object|Null} limit see above. + */ + setRecurrenceSetLimit: function(limit) { + this._limitRecurrenceSet = limit; + }, + + /** + * @param {String} name component name (like VCALENDAR). + * @return {QueryBuilder.Node} node instance. + */ + setComp: function(name) { + return this._compRoot = new Node(this, name); + }, + + /** + * Returns the root node of the document fragment. + */ + getComp: function() { + return this._compRoot; + }, + + toString: function() { + var content = ''; + var comp = this.getComp(); + + if (this._limitRecurrenceSet) { + content += this.template.tag( + ['caldav', 'limit-recurrence-set'], + this._limitRecurrenceSet + ); + } + + if (comp) { + content += comp.toString(); + } + + return this.template.tag( + this.tag, + this.attributes, + content + ); + } + + }; + + QueryBuilder.Node = Node; + module.exports = QueryBuilder; + +}.apply( + this, + (this.Caldav) ? + [Caldav('query_builder'), Caldav] : + [module, require('./caldav')] +)); + +/** +@namespace +*/ +(function(module, ns) { var Native; if (typeof(window) === 'undefined') { @@ -1900,153 +2218,6 @@ function write (chunk) { )); (function(module, ns) { - function CalendarData() { - this._hasItems = false; - this.struct = {}; - } - - CalendarData.prototype = { - - rootName: 'calendar-data', - compName: 'comp', - propName: 'prop', - - /** - * Appends a list of fields - * to a given iCalendar field set. - * - * @param {String} type iCal fieldset (VTODO, VEVENT,...). - */ - select: function(type, list) { - if (typeof(list) === 'undefined') { - list = true; - } - - var struct = this.struct; - this._hasItems = true; - - if (!(type in struct)) { - struct[type] = []; - } - - if (list instanceof Array) { - struct[type] = struct[type].concat(list); - } else { - struct[type] = 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', this.propName], - { name: value[i] } - ); - } - } - output += template.tag( - ['caldav', this.compName], - { name: tag }, - elementOutput || null - ); - elementOutput = ''; - } - - return output; - }, - - _defaultRender: function(template) { - return template.tag(['caldav', this.rootName]); - }, - - /** - * Renders CalendarData with a template. - * - * @param {WebCals.Template} template calendar to render. - * @return {String} <calendardata /> xml output. - */ - render: function(template) { - if (!this._hasItems) { - return this._defaultRender(template); - } - - var struct = this.struct; - var output = template.tag( - ['caldav', this.rootName], - template.tag( - ['caldav', this.compName], - { name: 'VCALENDAR' }, - this._renderFieldset(template, struct) - ) - ); - - return output; - } - }; - - - module.exports = CalendarData; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates/calendar_data'), Caldav] : - [module, require('../caldav')] -)); -(function(module, ns) { - - var CalendarData = ns.require('templates/calendar_data'); - - function CalendarFilter() { - CalendarData.call(this); - } - - CalendarFilter.prototype = { - - __proto__: CalendarData.prototype, - - add: CalendarData.prototype.select, - - _defaultRender: function(template) { - var inner = this._renderFieldset(template, { VCALENDAR: [{ VEVENT: true }] }); - return template.tag(['caldav', this.rootName], inner); - }, - - compName: 'comp-filter', - rootName: 'filter' - }; - - module.exports = CalendarFilter; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates/calendar_filter'), Caldav] : - [module, require('../caldav')] -)); - -(function(module, ns) { - var Base = { name: 'base', @@ -2721,8 +2892,7 @@ function write (chunk) { (function(module, ns) { var Propfind = ns.require('request/propfind'); - var CalendarData = ns.require('templates/calendar_data'); - var CalendarFilter = ns.require('templates/calendar_filter'); + var Builder = ns.require('query_builder'); /** * Creates a calendar query request. @@ -2737,10 +2907,19 @@ function write (chunk) { this.xhr.headers['Depth'] = this.depth || 1; this.xhr.method = 'REPORT'; - this.fields = new CalendarData(); - this.filters = new CalendarFilter(); this.template.rootTag = ['caldav', 'calendar-query']; + + this.data = new Builder({ + template: this.template + }); + + this.filter = new Builder({ + template: this.template, + tag: ['caldav', 'filter'], + propTag: ['caldav', 'prop-filter'], + compTag: ['caldav', 'comp-filter'] + }); } CalendarQuery.prototype = { @@ -2752,14 +2931,14 @@ function write (chunk) { props = this._props.join(''); - if (this.fields) { - props += this.fields.render(this.template); + if (this.data) { + props += this.data.toString(); } content = this.template.tag('prop', props); - if (this.filters) { - content += this.filters.render(this.template); + if (this.filter) { + content += this.filter.toString(); } return this.template.render(content); @@ -3013,19 +3192,6 @@ function write (chunk) { [module, require('../caldav')] )); -(function(module, ns) { - - module.exports = { - CalendarData: ns.require('templates/calendar_data'), - CalendarFilter: ns.require('templates/calendar_filter') - }; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates'), Caldav] : - [module, require('../caldav')] -)); /** @namespace */ @@ -3206,9 +3372,9 @@ function write (chunk) { exports.Responder = ns.require('responder'); exports.Sax = ns.require('sax'); exports.Template = ns.require('template'); + exports.QueryBuilder = ns.require('query_builder'); exports.Xhr = ns.require('xhr'); exports.Request = ns.require('request'); - exports.Templates = ns.require('templates'); exports.Connection = ns.require('connection'); exports.Resources = ns.require('resources'); diff --git a/lib/caldav/index.js b/lib/caldav/index.js index 4dd6852..cdce101 100644 --- a/lib/caldav/index.js +++ b/lib/caldav/index.js @@ -5,9 +5,9 @@ exports.Responder = ns.require('responder'); exports.Sax = ns.require('sax'); exports.Template = ns.require('template'); + exports.QueryBuilder = ns.require('query_builder'); exports.Xhr = ns.require('xhr'); exports.Request = ns.require('request'); - exports.Templates = ns.require('templates'); exports.Connection = ns.require('connection'); exports.Resources = ns.require('resources'); diff --git a/lib/caldav/request/calendar_query.js b/lib/caldav/request/calendar_query.js index 6ee1ec4..0d48788 100644 --- a/lib/caldav/request/calendar_query.js +++ b/lib/caldav/request/calendar_query.js @@ -1,8 +1,7 @@ (function(module, ns) { var Propfind = ns.require('request/propfind'); - var CalendarData = ns.require('templates/calendar_data'); - var CalendarFilter = ns.require('templates/calendar_filter'); + var Builder = ns.require('query_builder'); /** * Creates a calendar query request. @@ -17,10 +16,19 @@ this.xhr.headers['Depth'] = this.depth || 1; this.xhr.method = 'REPORT'; - this.fields = new CalendarData(); - this.filters = new CalendarFilter(); this.template.rootTag = ['caldav', 'calendar-query']; + + this.data = new Builder({ + template: this.template + }); + + this.filter = new Builder({ + template: this.template, + tag: ['caldav', 'filter'], + propTag: ['caldav', 'prop-filter'], + compTag: ['caldav', 'comp-filter'] + }); } CalendarQuery.prototype = { @@ -32,14 +40,14 @@ props = this._props.join(''); - if (this.fields) { - props += this.fields.render(this.template); + if (this.data) { + props += this.data.toString(); } content = this.template.tag('prop', props); - if (this.filters) { - content += this.filters.render(this.template); + if (this.filter) { + content += this.filter.toString(); } return this.template.render(content); diff --git a/lib/caldav/templates/calendar_data.js b/lib/caldav/templates/calendar_data.js deleted file mode 100644 index 5fcc4e8..0000000 --- a/lib/caldav/templates/calendar_data.js +++ /dev/null @@ -1,115 +0,0 @@ -(function(module, ns) { - - function CalendarData() { - this._hasItems = false; - this.struct = {}; - } - - CalendarData.prototype = { - - rootName: 'calendar-data', - compName: 'comp', - propName: 'prop', - - /** - * Appends a list of fields - * to a given iCalendar field set. - * - * @param {String} type iCal fieldset (VTODO, VEVENT,...). - */ - select: function(type, list) { - if (typeof(list) === 'undefined') { - list = true; - } - - var struct = this.struct; - this._hasItems = true; - - if (!(type in struct)) { - struct[type] = []; - } - - if (list instanceof Array) { - struct[type] = struct[type].concat(list); - } else { - struct[type] = 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', this.propName], - { name: value[i] } - ); - } - } - output += template.tag( - ['caldav', this.compName], - { name: tag }, - elementOutput || null - ); - elementOutput = ''; - } - - return output; - }, - - _defaultRender: function(template) { - return template.tag(['caldav', this.rootName]); - }, - - /** - * Renders CalendarData with a template. - * - * @param {WebCals.Template} template calendar to render. - * @return {String} <calendardata /> xml output. - */ - render: function(template) { - if (!this._hasItems) { - return this._defaultRender(template); - } - - var struct = this.struct; - var output = template.tag( - ['caldav', this.rootName], - template.tag( - ['caldav', this.compName], - { name: 'VCALENDAR' }, - this._renderFieldset(template, struct) - ) - ); - - return output; - } - }; - - - module.exports = CalendarData; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates/calendar_data'), Caldav] : - [module, require('../caldav')] -)); diff --git a/lib/caldav/templates/calendar_filter.js b/lib/caldav/templates/calendar_filter.js deleted file mode 100644 index a16f985..0000000 --- a/lib/caldav/templates/calendar_filter.js +++ /dev/null @@ -1,32 +0,0 @@ -(function(module, ns) { - - var CalendarData = ns.require('templates/calendar_data'); - - function CalendarFilter() { - CalendarData.call(this); - } - - CalendarFilter.prototype = { - - __proto__: CalendarData.prototype, - - add: CalendarData.prototype.select, - - _defaultRender: function(template) { - var inner = this._renderFieldset(template, { VCALENDAR: [{ VEVENT: true }] }); - return template.tag(['caldav', this.rootName], inner); - }, - - compName: 'comp-filter', - rootName: 'filter' - }; - - module.exports = CalendarFilter; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates/calendar_filter'), Caldav] : - [module, require('../caldav')] -)); - diff --git a/lib/caldav/templates/index.js b/lib/caldav/templates/index.js deleted file mode 100644 index 4e06cfd..0000000 --- a/lib/caldav/templates/index.js +++ /dev/null @@ -1,13 +0,0 @@ -(function(module, ns) { - - module.exports = { - CalendarData: ns.require('templates/calendar_data'), - CalendarFilter: ns.require('templates/calendar_filter') - }; - -}.apply( - this, - (this.Caldav) ? - [Caldav('templates'), Caldav] : - [module, require('../caldav')] -)); diff --git a/test/caldav/index_test.js b/test/caldav/index_test.js index 969c3a1..59012a4 100644 --- a/test/caldav/index_test.js +++ b/test/caldav/index_test.js @@ -24,13 +24,13 @@ suite('caldav', function() { }); test('namespaces', function() { - assert.ok(root); - assert.ok(root.Request); - assert.ok(root.Templates); - assert.ok(root.Xhr); - assert.ok(root.Connection); - assert.ok(root.Resources); - assert.ok(root.Resources.Calendar); + assert.ok(root, 'Caldav'); + assert.ok(root.Request, 'Caldav.Request'); + assert.ok(root.QueryBuilder, 'Caldav.QueryBuilder'); + assert.ok(root.Xhr, 'Caldav.Xhr'); + assert.ok(root.Connection, 'Caldav.Connection'); + assert.ok(root.Resources, 'Caldav.Resources'); + assert.ok(root.Resources.Calendar, 'Calendar.Resources.Calendar'); }); }); diff --git a/test/caldav/request/calendar_query_test.js b/test/caldav/request/calendar_query_test.js index e28940f..e1824b4 100644 --- a/test/caldav/request/calendar_query_test.js +++ b/test/caldav/request/calendar_query_test.js @@ -1,13 +1,13 @@ requireRequest(); +testSupport.lib('query_builder'); testSupport.lib('request/propfind'); testSupport.lib('request/calendar_query'); suite('caldav/request/calendar_query', function() { var Propfind, FakeXhr, - CalendarData, + Builder, CalendarQuery, - CalendarFilter, Connection, con, Xhr, @@ -21,8 +21,7 @@ suite('caldav/request/calendar_query', function() { suiteSetup(function() { // this is way to much stuff Propfind = Caldav.require('request/propfind'); - CalendarData = Caldav.require('templates/calendar_data'); - CalendarFilter = Caldav.require('templates/calendar_filter'); + Builder = Caldav.require('query_builder'); CalendarQuery = Caldav.require('request/calendar_query'); SaxResponse = Caldav.require('sax/dav_response'); Connection = Caldav.require('connection'); @@ -50,15 +49,21 @@ suite('caldav/request/calendar_query', function() { assert.equal(subject.xhr.headers['Depth'], 1); assert.equal(subject.xhr.method, 'REPORT'); - assert.instanceOf(subject.fields, CalendarData); - assert.instanceOf(subject.filters, CalendarFilter); + assert.instanceOf(subject.data, Builder); + assert.instanceOf(subject.filter, Builder); }); test('#_createPayload', function() { subject.prop('getetag'); - subject.fields.select('VEVENT', ['NAME']); - subject.filters.add('VEVENT', true); + var cal = subject.data. + setComp('VCALENDAR'). + comp('VEVENT'). + prop('NAME'); + + var filter = subject.filter. + setComp('VCALENDAR'). + comp('VEVENT'); var props = [ '<N0:getetag />', '<N1:calendar-data>', @@ -89,7 +94,6 @@ suite('caldav/request/calendar_query', function() { }); suite('integration', function() { - return; var xml, data, result, diff --git a/test/caldav/templates/calendar_data_test.js b/test/caldav/templates/calendar_data_test.js deleted file mode 100644 index 9a21926..0000000 --- a/test/caldav/templates/calendar_data_test.js +++ /dev/null @@ -1,70 +0,0 @@ -requireRequest(); -testSupport.lib('templates/calendar_data'); - -suite('caldav/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 = Caldav.require('templates/calendar_data'); - Template = Caldav.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(''); - - test('without items', function() { - var output = subject.render(template); - assert.equal( - output, - '<N0:calendar-data />' - ); - }); - - test('output', function() { - select(); - var output = subject.render(template); - assert.equal(output, expected); - }); - }); - -}); diff --git a/test/caldav/templates/calendar_filter_test.js b/test/caldav/templates/calendar_filter_test.js deleted file mode 100644 index d9ce2ab..0000000 --- a/test/caldav/templates/calendar_filter_test.js +++ /dev/null @@ -1,53 +0,0 @@ -requireRequest(); -testSupport.lib('templates/calendar_data'); -testSupport.lib('templates/calendar_filter'); - -suite('caldav/templates/calendar_filter', function() { - var CalendarFilter; - var Template; - - var subject; - var template; - - function filter() { - subject.add('VEVENT', true); - } - - suiteSetup(function() { - CalendarFilter = Caldav.require('templates/calendar_filter'); - Template = Caldav.require('template'); - }); - - setup(function() { - subject = new CalendarFilter(); - template = new Template('root'); - }); - - test('initialization', function() { - assert.deepEqual(subject.struct, {}); - }); - - suite('#render', function() { - var output; - var expected; - - expected = [ - '<N0:filter>', - '<N0:comp-filter name="VCALENDAR">', - '<N0:comp-filter name="VEVENT" />', - '</N0:comp-filter>', - '</N0:filter>' - ].join(''); - - setup(function() { - filter(); - }); - - test('output', function() { - var output = subject.render(template); - assert.equal(output, expected); - }); - }); - -}); - |