protocol-caldav 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "scampi"
5
3
  require "builder"
6
4
  require "protocol/caldav"
7
5
 
@@ -74,52 +72,52 @@ module Protocol
74
72
  end
75
73
  end
76
74
 
77
- test do
78
- def normalize(xml)
79
- xml.gsub(/>\s+</, '><').strip
80
- end
75
+ __END__
81
76
 
82
- describe "Protocol::Caldav::Item" do
83
- def make_item(**opts)
84
- defaults = {
85
- path: Protocol::Caldav::Path.new("/calendars/admin/work/event.ics"),
86
- body: "BEGIN:VCALENDAR\r\nEND:VCALENDAR",
87
- content_type: "text/calendar",
88
- etag: '"abc123"'
89
- }
90
- Protocol::Caldav::Item.new(**defaults.merge(opts))
91
- end
77
+ def normalize(xml)
78
+ xml.gsub(/>\s+</, '><').strip
79
+ end
92
80
 
93
- it "exposes path, body, content_type, etag" do
94
- item = make_item
95
- item.path.to_s.should.equal "/calendars/admin/work/event.ics"
96
- item.body.should.include "VCALENDAR"
97
- item.content_type.should.equal "text/calendar"
98
- item.etag.should.equal '"abc123"'
99
- end
81
+ describe "Protocol::Caldav::Item" do
82
+ def make_item(**opts)
83
+ defaults = {
84
+ path: Protocol::Caldav::Path.new("/calendars/admin/work/event.ics"),
85
+ body: "BEGIN:VCALENDAR\r\nEND:VCALENDAR",
86
+ content_type: "text/calendar",
87
+ etag: '"abc123"'
88
+ }
89
+ Protocol::Caldav::Item.new(**defaults.merge(opts))
90
+ end
100
91
 
101
- it "new? returns new_record state" do
102
- make_item(new_record: true).new?.should.equal true
103
- make_item(new_record: false).new?.should.equal false
104
- end
92
+ it "exposes path, body, content_type, etag" do
93
+ item = make_item
94
+ item.path.to_s.should.equal "/calendars/admin/work/event.ics"
95
+ item.body.should.include "VCALENDAR"
96
+ item.content_type.should.equal "text/calendar"
97
+ item.etag.should.equal '"abc123"'
98
+ end
105
99
 
106
- it "to_propfind_xml includes etag and content-type" do
107
- xml = make_item.to_propfind_xml
108
- xml.should.include "getetag"
109
- xml.should.include "getcontenttype"
110
- xml.should.include "text/calendar"
111
- end
100
+ it "new? returns new_record state" do
101
+ make_item(new_record: true).new?.should.equal true
102
+ make_item(new_record: false).new?.should.equal false
103
+ end
112
104
 
113
- it "to_report_xml includes data tag with body" do
114
- xml = make_item.to_report_xml(data_tag: "c:calendar-data")
115
- xml.should.include "c:calendar-data"
116
- xml.should.include "VCALENDAR"
117
- end
105
+ it "to_propfind_xml includes etag and content-type" do
106
+ xml = make_item.to_propfind_xml
107
+ xml.should.include "getetag"
108
+ xml.should.include "getcontenttype"
109
+ xml.should.include "text/calendar"
110
+ end
118
111
 
119
- it "to_propname_xml includes empty prop elements" do
120
- xml = make_item.to_propname_xml
121
- xml.should.include "<d:getetag/>"
122
- xml.should.include "<d:getcontenttype/>"
123
- end
112
+ it "to_report_xml includes data tag with body" do
113
+ xml = make_item.to_report_xml(data_tag: "c:calendar-data")
114
+ xml.should.include "c:calendar-data"
115
+ xml.should.include "VCALENDAR"
116
+ end
117
+
118
+ it "to_propname_xml includes empty prop elements" do
119
+ xml = make_item.to_propname_xml
120
+ xml.should.include "<d:getetag/>"
121
+ xml.should.include "<d:getcontenttype/>"
124
122
  end
125
123
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "scampi"
5
3
  require "builder"
6
4
 
7
5
  module Protocol
@@ -24,60 +22,59 @@ module Protocol
24
22
  end
25
23
  end
26
24
 
25
+ __END__
27
26
 
28
- test do
29
- def normalize(xml)
30
- xml.gsub(/>\s+</, '><').strip
31
- end
27
+ def normalize(xml)
28
+ xml.gsub(/>\s+</, '><').strip
29
+ end
32
30
 
33
- # Minimal wrapper so tests can pass objects with build_xml
34
- class FakeResponse
35
- def initialize(href)
36
- @href = href
37
- end
31
+ # Minimal wrapper so tests can pass objects with build_xml
32
+ class FakeResponse
33
+ def initialize(href)
34
+ @href = href
35
+ end
38
36
 
39
- def build_xml(xml)
40
- xml.tag!("d:response") { xml.tag!("d:href", @href) }
41
- end
37
+ def build_xml(xml)
38
+ xml.tag!("d:response") { xml.tag!("d:href", @href) }
42
39
  end
40
+ end
43
41
 
44
- describe "Protocol::Caldav::Multistatus" do
45
- it "declares all four required namespaces" do
46
- xml = Protocol::Caldav::Multistatus.new([]).to_xml
47
- xml.should.include 'xmlns:d="DAV:"'
48
- xml.should.include 'xmlns:c="urn:ietf:params:xml:ns:caldav"'
49
- xml.should.include 'xmlns:cr="urn:ietf:params:xml:ns:carddav"'
50
- xml.should.include 'xmlns:cs="http://calendarserver.org/ns/"'
51
- end
42
+ describe "Protocol::Caldav::Multistatus" do
43
+ it "declares all four required namespaces" do
44
+ xml = Protocol::Caldav::Multistatus.new([]).to_xml
45
+ xml.should.include 'xmlns:d="DAV:"'
46
+ xml.should.include 'xmlns:c="urn:ietf:params:xml:ns:caldav"'
47
+ xml.should.include 'xmlns:cr="urn:ietf:params:xml:ns:carddav"'
48
+ xml.should.include 'xmlns:cs="http://calendarserver.org/ns/"'
49
+ end
52
50
 
53
- it "emits responses in the order given" do
54
- responses = [FakeResponse.new("/a"), FakeResponse.new("/b")]
55
- xml = Protocol::Caldav::Multistatus.new(responses).to_xml
56
- xml.index("/a").should.be < xml.index("/b")
57
- end
51
+ it "emits responses in the order given" do
52
+ responses = [FakeResponse.new("/a"), FakeResponse.new("/b")]
53
+ xml = Protocol::Caldav::Multistatus.new(responses).to_xml
54
+ xml.index("/a").should.be < xml.index("/b")
55
+ end
58
56
 
59
- it "produces valid XML for empty response array" do
60
- xml = Protocol::Caldav::Multistatus.new([]).to_xml
61
- xml.should.include '<?xml version="1.0"'
62
- xml.should.include '<d:multistatus'
63
- xml.should.include '</d:multistatus>'
64
- end
57
+ it "produces valid XML for empty response array" do
58
+ xml = Protocol::Caldav::Multistatus.new([]).to_xml
59
+ xml.should.include '<?xml version="1.0"'
60
+ xml.should.include '<d:multistatus'
61
+ xml.should.include '</d:multistatus>'
62
+ end
65
63
 
66
- it "does not double-escape when using builder" do
67
- xml = Protocol::Caldav::Multistatus.new.to_xml do |x|
68
- x.tag!("d:response") { x.tag!("d:href", "/Work & Personal") }
69
- end
70
- xml.should.include '&amp;'
71
- xml.should.not.include '&amp;amp;'
64
+ it "does not double-escape when using builder" do
65
+ xml = Protocol::Caldav::Multistatus.new.to_xml do |x|
66
+ x.tag!("d:response") { x.tag!("d:href", "/Work & Personal") }
72
67
  end
68
+ xml.should.include '&amp;'
69
+ xml.should.not.include '&amp;amp;'
70
+ end
73
71
 
74
- it "supports block form for custom content" do
75
- xml = Protocol::Caldav::Multistatus.new.to_xml do |x|
76
- x.tag!("d:response") { x.tag!("d:href", "/test") }
77
- x.tag!("d:sync-token", "token-123")
78
- end
79
- xml.should.include '/test'
80
- xml.should.include 'token-123'
72
+ it "supports block form for custom content" do
73
+ xml = Protocol::Caldav::Multistatus.new.to_xml do |x|
74
+ x.tag!("d:response") { x.tag!("d:href", "/test") }
75
+ x.tag!("d:sync-token", "token-123")
81
76
  end
77
+ xml.should.include '/test'
78
+ xml.should.include 'token-123'
82
79
  end
83
80
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "scampi"
5
3
  require "builder"
6
4
  require "protocol/caldav"
7
5
 
@@ -12,7 +10,9 @@ module Protocol
12
10
 
13
11
  def initialize(raw, storage_class: nil)
14
12
  p = raw.to_s.gsub(%r{/+}, '/')
15
- p = "/#{p}" unless p.start_with?('/')
13
+ unless p.start_with?('/')
14
+ p = "/#{p}"
15
+ end
16
16
  @to_s = p
17
17
  @storage_class = storage_class
18
18
  end
@@ -32,7 +32,9 @@ module Protocol
32
32
 
33
33
  def child_of?(other)
34
34
  parent_str = other.to_s
35
- parent_str = "#{parent_str}/" unless parent_str.end_with?('/')
35
+ unless parent_str.end_with?('/')
36
+ parent_str = "#{parent_str}/"
37
+ end
36
38
  if @to_s.start_with?(parent_str)
37
39
  remainder = @to_s[parent_str.length..]
38
40
  remainder.chomp('/').count('/').zero? && !remainder.chomp('/').empty?
@@ -42,7 +44,9 @@ module Protocol
42
44
  end
43
45
 
44
46
  def parent_exists?
45
- raise ArgumentError, "storage_class required for parent_exists?" unless @storage_class
47
+ unless @storage_class
48
+ raise ArgumentError, "storage_class required for parent_exists?"
49
+ end
46
50
 
47
51
  if parent.depth <= 2
48
52
  true
@@ -88,103 +92,102 @@ module Protocol
88
92
  end
89
93
  end
90
94
 
95
+ __END__
91
96
 
92
- test do
93
- describe "Protocol::Caldav::Path" do
94
- it "normalizes // to /" do
95
- Protocol::Caldav::Path.new("//foo//bar").to_s.should.equal "/foo/bar"
96
- end
97
+ describe "Protocol::Caldav::Path" do
98
+ it "normalizes // to /" do
99
+ Protocol::Caldav::Path.new("//foo//bar").to_s.should.equal "/foo/bar"
100
+ end
97
101
 
98
- it "normalizes leading ///foo to /foo" do
99
- Protocol::Caldav::Path.new("///foo").to_s.should.equal "/foo"
100
- end
102
+ it "normalizes leading ///foo to /foo" do
103
+ Protocol::Caldav::Path.new("///foo").to_s.should.equal "/foo"
104
+ end
101
105
 
102
- it "adds leading / if missing" do
103
- Protocol::Caldav::Path.new("foo/bar").to_s.should.equal "/foo/bar"
104
- end
106
+ it "adds leading / if missing" do
107
+ Protocol::Caldav::Path.new("foo/bar").to_s.should.equal "/foo/bar"
108
+ end
105
109
 
106
- describe "#parent" do
107
- it "parent of /a/b/c/ is /a/b/" do
108
- Protocol::Caldav::Path.new("/a/b/c/").parent.to_s.should.equal "/a/b/"
109
- end
110
+ describe "#parent" do
111
+ it "parent of /a/b/c/ is /a/b/" do
112
+ Protocol::Caldav::Path.new("/a/b/c/").parent.to_s.should.equal "/a/b/"
113
+ end
110
114
 
111
- it "parent of /a/ is /" do
112
- Protocol::Caldav::Path.new("/a/").parent.to_s.should.equal "/"
113
- end
115
+ it "parent of /a/ is /" do
116
+ Protocol::Caldav::Path.new("/a/").parent.to_s.should.equal "/"
117
+ end
114
118
 
115
- it "parent of / is / (idempotent)" do
116
- Protocol::Caldav::Path.new("/").parent.to_s.should.equal "/"
117
- end
119
+ it "parent of / is / (idempotent)" do
120
+ Protocol::Caldav::Path.new("/").parent.to_s.should.equal "/"
118
121
  end
122
+ end
119
123
 
120
- describe "#depth" do
121
- it "depth of / is 0" do
122
- Protocol::Caldav::Path.new("/").depth.should.equal 0
123
- end
124
+ describe "#depth" do
125
+ it "depth of / is 0" do
126
+ Protocol::Caldav::Path.new("/").depth.should.equal 0
127
+ end
124
128
 
125
- it "depth of /a/ is 1" do
126
- Protocol::Caldav::Path.new("/a/").depth.should.equal 1
127
- end
129
+ it "depth of /a/ is 1" do
130
+ Protocol::Caldav::Path.new("/a/").depth.should.equal 1
131
+ end
128
132
 
129
- it "depth of /a/b is 2 (trailing-slash-insensitive)" do
130
- Protocol::Caldav::Path.new("/a/b").depth.should.equal 2
131
- end
133
+ it "depth of /a/b is 2 (trailing-slash-insensitive)" do
134
+ Protocol::Caldav::Path.new("/a/b").depth.should.equal 2
132
135
  end
136
+ end
133
137
 
134
- describe "#child_of?" do
135
- it "returns true for direct child" do
136
- child = Protocol::Caldav::Path.new("/a/b/")
137
- parent = Protocol::Caldav::Path.new("/a/")
138
- child.child_of?(parent).should.equal true
139
- end
138
+ describe "#child_of?" do
139
+ it "returns true for direct child" do
140
+ child = Protocol::Caldav::Path.new("/a/b/")
141
+ parent = Protocol::Caldav::Path.new("/a/")
142
+ child.child_of?(parent).should.equal true
143
+ end
140
144
 
141
- it "returns false for grandchild" do
142
- grandchild = Protocol::Caldav::Path.new("/a/b/c/")
143
- grandparent = Protocol::Caldav::Path.new("/a/")
144
- grandchild.child_of?(grandparent).should.equal false
145
- end
145
+ it "returns false for grandchild" do
146
+ grandchild = Protocol::Caldav::Path.new("/a/b/c/")
147
+ grandparent = Protocol::Caldav::Path.new("/a/")
148
+ grandchild.child_of?(grandparent).should.equal false
149
+ end
146
150
 
147
- it "returns false for sibling" do
148
- a = Protocol::Caldav::Path.new("/a/b/")
149
- b = Protocol::Caldav::Path.new("/a/c/")
150
- a.child_of?(b).should.equal false
151
- end
151
+ it "returns false for sibling" do
152
+ a = Protocol::Caldav::Path.new("/a/b/")
153
+ b = Protocol::Caldav::Path.new("/a/c/")
154
+ a.child_of?(b).should.equal false
155
+ end
152
156
 
153
- it "returns false for self" do
154
- a = Protocol::Caldav::Path.new("/a/")
155
- a.child_of?(a).should.equal false
156
- end
157
+ it "returns false for self" do
158
+ a = Protocol::Caldav::Path.new("/a/")
159
+ a.child_of?(a).should.equal false
157
160
  end
161
+ end
158
162
 
159
- describe "#ensure_trailing_slash" do
160
- it "is idempotent on a slashed path" do
161
- Protocol::Caldav::Path.new("/a/").ensure_trailing_slash.to_s.should.equal "/a/"
162
- end
163
+ describe "#ensure_trailing_slash" do
164
+ it "is idempotent on a slashed path" do
165
+ Protocol::Caldav::Path.new("/a/").ensure_trailing_slash.to_s.should.equal "/a/"
166
+ end
163
167
 
164
- it "adds slash to unslashed" do
165
- Protocol::Caldav::Path.new("/a").ensure_trailing_slash.to_s.should.equal "/a/"
166
- end
168
+ it "adds slash to unslashed" do
169
+ Protocol::Caldav::Path.new("/a").ensure_trailing_slash.to_s.should.equal "/a/"
167
170
  end
171
+ end
168
172
 
169
- describe "#start_with?" do
170
- it "delegates to string semantics" do
171
- Protocol::Caldav::Path.new("/calendars/admin/").start_with?("/calendars/").should.equal true
172
- Protocol::Caldav::Path.new("/addressbooks/admin/").start_with?("/calendars/").should.equal false
173
- end
173
+ describe "#start_with?" do
174
+ it "delegates to string semantics" do
175
+ Protocol::Caldav::Path.new("/calendars/admin/").start_with?("/calendars/").should.equal true
176
+ Protocol::Caldav::Path.new("/addressbooks/admin/").start_with?("/calendars/").should.equal false
174
177
  end
178
+ end
175
179
 
176
- describe "#==" do
177
- it "paths with same string are equal" do
178
- a = Protocol::Caldav::Path.new("/a/")
179
- b = Protocol::Caldav::Path.new("/a/")
180
- (a == b).should.equal true
181
- end
180
+ describe "#==" do
181
+ it "paths with same string are equal" do
182
+ a = Protocol::Caldav::Path.new("/a/")
183
+ b = Protocol::Caldav::Path.new("/a/")
184
+ (a == b).should.equal true
185
+ end
182
186
 
183
- it "paths from different storage_class but same string compare equal" do
184
- a = Protocol::Caldav::Path.new("/a/", storage_class: Object.new)
185
- b = Protocol::Caldav::Path.new("/a/", storage_class: Object.new)
186
- (a == b).should.equal true
187
- end
187
+ it "paths from different storage_class but same string compare equal" do
188
+ a = Protocol::Caldav::Path.new("/a/", storage_class: Object.new)
189
+ b = Protocol::Caldav::Path.new("/a/", storage_class: Object.new)
190
+ (a == b).should.equal true
188
191
  end
189
192
  end
190
193
  end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "scampi"
5
-
6
3
  module Protocol
7
4
  module Caldav
8
5
  class Storage
@@ -86,35 +83,34 @@ module Protocol
86
83
  end
87
84
  end
88
85
 
89
-
90
- test do
91
- describe "Protocol::Caldav::Storage" do
92
- it "every method raises NotImplementedError" do
93
- s = Protocol::Caldav::Storage.new
94
- methods = %i[create_collection get_collection delete_collection list_collections
95
- update_collection collection_exists? get_item put_item delete_item
96
- list_items move_item get_multi exists? etag snapshot_sync sync_changes]
97
- three_arg = %i[put_item]
98
- two_arg = %i[update_collection move_item sync_changes]
99
- methods.each do |m|
100
- if three_arg.include?(m)
101
- lambda { s.send(m, "/x", "body", "ct") }.should.raise NotImplementedError
102
- elsif two_arg.include?(m)
103
- lambda { s.send(m, "/x", {}) }.should.raise NotImplementedError
104
- else
105
- lambda { s.send(m, "/x") }.should.raise NotImplementedError
106
- end
86
+ __END__
87
+
88
+ describe "Protocol::Caldav::Storage" do
89
+ it "every method raises NotImplementedError" do
90
+ s = Protocol::Caldav::Storage.new
91
+ methods = %i[create_collection get_collection delete_collection list_collections
92
+ update_collection collection_exists? get_item put_item delete_item
93
+ list_items move_item get_multi exists? etag snapshot_sync sync_changes]
94
+ three_arg = %i[put_item]
95
+ two_arg = %i[update_collection move_item sync_changes]
96
+ methods.each do |m|
97
+ if three_arg.include?(m)
98
+ lambda { s.send(m, "/x", "body", "ct") }.should.raise NotImplementedError
99
+ elsif two_arg.include?(m)
100
+ lambda { s.send(m, "/x", {}) }.should.raise NotImplementedError
101
+ else
102
+ lambda { s.send(m, "/x") }.should.raise NotImplementedError
107
103
  end
108
104
  end
105
+ end
109
106
 
110
- it "can be subclassed with partial implementation" do
111
- klass = Class.new(Protocol::Caldav::Storage) do
112
- def exists?(path)
113
- true
114
- end
107
+ it "can be subclassed with partial implementation" do
108
+ klass = Class.new(Protocol::Caldav::Storage) do
109
+ def exists?(path)
110
+ true
115
111
  end
116
- klass.new.exists?("/x").should.equal true
117
- lambda { klass.new.get_item("/x") }.should.raise NotImplementedError
118
112
  end
113
+ klass.new.exists?("/x").should.equal true
114
+ lambda { klass.new.get_item("/x") }.should.raise NotImplementedError
119
115
  end
120
116
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "scampi"
5
3
  require "protocol/caldav"
6
4
 
7
5
  module Protocol
@@ -24,35 +22,35 @@ module Protocol
24
22
  end
25
23
  end
26
24
 
27
- test do
28
- describe "Protocol::Caldav::Vcard::Card" do
29
- def prop(name, value)
30
- Protocol::Caldav::Ical::Property.new(name: name, params: {}, value: value)
31
- end
25
+ __END__
32
26
 
33
- it "find_property returns the first matching property" do
34
- card = Protocol::Caldav::Vcard::Card.new(properties: [prop("FN", "John"), prop("FN", "Jane")])
35
- card.find_property("FN").value.should.equal "John"
36
- end
27
+ describe "Protocol::Caldav::Vcard::Card" do
28
+ def prop(name, value)
29
+ Protocol::Caldav::Ical::Property.new(name: name, params: {}, value: value)
30
+ end
37
31
 
38
- it "find_property is case-insensitive" do
39
- card = Protocol::Caldav::Vcard::Card.new(properties: [prop("FN", "John")])
40
- card.find_property("fn").value.should.equal "John"
41
- end
32
+ it "find_property returns the first matching property" do
33
+ card = Protocol::Caldav::Vcard::Card.new(properties: [prop("FN", "John"), prop("FN", "Jane")])
34
+ card.find_property("FN").value.should.equal "John"
35
+ end
42
36
 
43
- it "find_property returns nil when absent" do
44
- card = Protocol::Caldav::Vcard::Card.new(properties: [])
45
- card.find_property("FN").should.be.nil
46
- end
37
+ it "find_property is case-insensitive" do
38
+ card = Protocol::Caldav::Vcard::Card.new(properties: [prop("FN", "John")])
39
+ card.find_property("fn").value.should.equal "John"
40
+ end
47
41
 
48
- it "has no sub-component finder (vCards don't nest)" do
49
- card = Protocol::Caldav::Vcard::Card.new
50
- card.should.not.respond_to(:find_components)
51
- end
42
+ it "find_property returns nil when absent" do
43
+ card = Protocol::Caldav::Vcard::Card.new(properties: [])
44
+ card.find_property("FN").should.be.nil
45
+ end
52
46
 
53
- it "find_all_properties returns all matching" do
54
- card = Protocol::Caldav::Vcard::Card.new(properties: [prop("TEL", "123"), prop("EMAIL", "x"), prop("TEL", "456")])
55
- card.find_all_properties("TEL").length.should.equal 2
56
- end
47
+ it "has no sub-component finder (vCards don't nest)" do
48
+ card = Protocol::Caldav::Vcard::Card.new
49
+ card.should.not.respond_to(:find_components)
50
+ end
51
+
52
+ it "find_all_properties returns all matching" do
53
+ card = Protocol::Caldav::Vcard::Card.new(properties: [prop("TEL", "123"), prop("EMAIL", "x"), prop("TEL", "456")])
54
+ card.find_all_properties("TEL").length.should.equal 2
57
55
  end
58
56
  end