calendav 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bae509ffc0254b00db9e4380a76278770a0868093ff69b597b6b10fcf9ecd01
4
- data.tar.gz: 26cfe5ccbc19dba770cf2d255cbb36bc3529039903af8d28281536f70cb55c49
3
+ metadata.gz: fc244efe85f65a2f9c4da19099a2a2e564a0b4fda5a1fafdcf6f37dd436c1f12
4
+ data.tar.gz: 101adff024b6f5d6b9d6fca3ea96c273facacbd0f66989175c0be8171633c228
5
5
  SHA512:
6
- metadata.gz: 56fd5c731ad0d4b05d29a68df6624bad4809a6a146806c8190ba765b233e39598572711ff6f5f61a59df09a8d919090b45641bfbc2214a1ad746f4a7f5bf8662
7
- data.tar.gz: fa897448f63e9c5a04f8c97acebb950d0213fbc8aa10eb8d4069aaaafbe9849148dafe526de9c78a6d947c4a43eaaa78260665dfd05d66b429c21d5e1caf5a7e
6
+ metadata.gz: 1ee524964c2799df6fdf47dce9d007c6332ebe8e6fe8d2f9265f57bfccba4117d7a508520267fa5e025dcb8c209efeb1bd01f1c73f31edf1ee4cded5d8259def
7
+ data.tar.gz: 2df0276f3030c0fd1ea0cc37a32833326e7e2a0072aa4c6260c92e0e35ef635816e1b047d65b9db63e8b9c937ce4edc2c86ecb45d34ad8410c49229b5fcd06ed
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.4.0 - 2023-02-27
4
+
5
+ * **Breaking**: calls to create/update events return event objects that only have a URL and etag populated (so: no calendar data), or nil if the request failed due to an etag precondition. This is instead of returning true on success or false on failure.
6
+ * Removed test files from the gem/gemspec.
7
+ * Increased nuance of error handler, raising a RedirectError (with location method) if the CalDAV server returns a redirect status.
8
+
3
9
  ## 0.3.0 - 2022-03-14
4
10
 
5
11
  * Add location to event wrapper.
data/README.md CHANGED
@@ -121,7 +121,8 @@ end
121
121
  ics.publish
122
122
 
123
123
  identifier = "#{SecureRandom.uuid}.ics"
124
- event_url = client.events.create(calendar.url, identifier, ics.to_ical)
124
+ # The returned event has just the URL and the etag, no calendar data:
125
+ event_scaffold = client.events.create(calendar.url, identifier, ics.to_ical)
125
126
  ```
126
127
 
127
128
  *Please note*: some providers (definitely Google, possibly others) will not keep your supplied event identifier, but generate a new one. So, if you need an ongoing reference to the event, save the returned URL (rather than combining the calendar URL and your identifier).
@@ -129,17 +130,17 @@ event_url = client.events.create(calendar.url, identifier, ics.to_ical)
129
130
  Updating events is done in a similar manner - with the event's URL and the updated iCalendar content:
130
131
 
131
132
  ```ruby
132
- client.events.update(event_url, ics.to_ical)
133
+ event_scaffold = client.events.update(event_url, ics.to_ical)
133
134
  ```
134
135
 
135
- To ensure you're only changing a known version of an event, it's recommended you use that version's etag as a precondition check (the update call will return false if the event on the server has a different etag value):
136
+ To ensure you're only changing a known version of an event, it's recommended you use that version's etag as a precondition check (the update call will return nil if the event on the server has a different etag value):
136
137
 
137
138
  ```ruby
138
- event = client.events.find(event_url)
139
+ event = client.events.find(event_scaffold.url)
139
140
 
140
141
  # figure out the changes you want to make, generate the new ical data, and then:
141
142
 
142
- client.events.update(event_url, modified_ical, etag: event.etag)
143
+ client.events.update(event_scaffold.url, modified_ical, etag: event.etag)
143
144
  ```
144
145
 
145
146
  Deletion of events is done via the event's URL as well - some providers (including Apple) support the etag precondition check for this, but others (including Google) do not. In the latter situation, the deletion will happen regardless of the server event's etag value.
@@ -17,7 +17,10 @@ module Calendav
17
17
  event_url = merged_url(calendar_url, event_identifier)
18
18
  result = endpoint.put(ics, url: event_url, content_type: :ics)
19
19
 
20
- result.headers["Location"] || event_url
20
+ Event.new(
21
+ url: result.headers["Location"] || event_url,
22
+ etag: result.headers["ETag"]
23
+ )
21
24
  end
22
25
 
23
26
  def delete(event_url, etag: nil)
@@ -46,13 +49,16 @@ module Calendav
46
49
  end
47
50
 
48
51
  def update(event_url, ics, etag: nil)
49
- endpoint.put(
52
+ result = endpoint.put(
50
53
  ics, url: event_url, content_type: :ics, etag: etag
51
54
  )
52
55
 
53
- true
56
+ Event.new(
57
+ url: event_url,
58
+ etag: result.headers["ETag"]
59
+ )
54
60
  rescue PreconditionError
55
- false
61
+ nil
56
62
  end
57
63
 
58
64
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "./contextual_url"
4
- require_relative "./errors"
4
+ require_relative "./error_handler"
5
5
  require_relative "./parsers/response_xml"
6
6
 
7
7
  module Calendav
@@ -109,11 +109,7 @@ module Calendav
109
109
  verb, ContextualURL.call(credentials.host, url), body: body
110
110
  )
111
111
 
112
- return response if response.status.success?
113
-
114
- raise PreconditionError, response if response.status.code == 412
115
-
116
- raise RequestError, response
112
+ response.status.success? ? response : ErrorHandler.call(response)
117
113
  end
118
114
 
119
115
  def parse(response)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./errors"
4
+
5
+ module Calendav
6
+ class ErrorHandler
7
+ def self.call(...)
8
+ new(...).call
9
+ end
10
+
11
+ def initialize(response)
12
+ @response = response
13
+ end
14
+
15
+ def call
16
+ raise PreconditionError, response if status.code == 412
17
+ raise RedirectError, response if status.redirect?
18
+
19
+ raise RequestError, response
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :response
25
+
26
+ def headers
27
+ response.headers
28
+ end
29
+
30
+ def status
31
+ response.status
32
+ end
33
+ end
34
+ end
@@ -24,5 +24,11 @@ module Calendav
24
24
  end
25
25
  end
26
26
 
27
+ class RedirectError < RequestError
28
+ def location
29
+ response.headers["Location"]
30
+ end
31
+ end
32
+
27
33
  PreconditionError = Class.new(RequestError)
28
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calendav
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-14 00:00:00.000000000 Z
11
+ date: 2023-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -213,12 +213,9 @@ executables: []
213
213
  extensions: []
214
214
  extra_rdoc_files: []
215
215
  files:
216
- - ".rspec"
217
216
  - CHANGELOG.md
218
- - Gemfile
219
217
  - LICENSE.md
220
218
  - README.md
221
- - Rakefile
222
219
  - lib/calendav.rb
223
220
  - lib/calendav/calendar.rb
224
221
  - lib/calendav/client.rb
@@ -230,6 +227,7 @@ files:
230
227
  - lib/calendav/credentials/google.rb
231
228
  - lib/calendav/credentials/standard.rb
232
229
  - lib/calendav/endpoint.rb
230
+ - lib/calendav/error_handler.rb
233
231
  - lib/calendav/errors.rb
234
232
  - lib/calendav/event.rb
235
233
  - lib/calendav/multi_response.rb
@@ -246,16 +244,6 @@ files:
246
244
  - lib/calendav/requests/sync_collection.rb
247
245
  - lib/calendav/requests/update_calendar.rb
248
246
  - lib/calendav/sync_collection.rb
249
- - spec/acceptance/apple_spec.rb
250
- - spec/acceptance/google_spec.rb
251
- - spec/acceptance/radicale_spec.rb
252
- - spec/acceptance/shared.rb
253
- - spec/data/radicale/config.ini
254
- - spec/data/radicale/users
255
- - spec/spec_helper.rb
256
- - spec/support/encoded_matchers.rb
257
- - spec/support/event_helpers.rb
258
- - spec/support/vcr.rb
259
247
  homepage: https://github.com/pat/calendav
260
248
  licenses:
261
249
  - Hippocratic-2.1
@@ -283,17 +271,4 @@ rubygems_version: 3.2.32
283
271
  signing_key:
284
272
  specification_version: 4
285
273
  summary: CalDAV client
286
- test_files:
287
- - spec/acceptance/apple_spec.rb
288
- - spec/acceptance/google_spec.rb
289
- - spec/acceptance/radicale_spec.rb
290
- - spec/acceptance/shared.rb
291
- - spec/data/radicale/config.ini
292
- - spec/data/radicale/users
293
- - spec/spec_helper.rb
294
- - spec/support/encoded_matchers.rb
295
- - spec/support/event_helpers.rb
296
- - spec/support/vcr.rb
297
- - ".rspec"
298
- - Gemfile
299
- - Rakefile
274
+ test_files: []
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- gemspec
6
-
7
- gem "icalendar",
8
- git: "https://github.com/pat/icalendar.git",
9
- branch: "fix/activesupport-7"
data/Rakefile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- require "rubocop/rake_task"
9
-
10
- RuboCop::RakeTask.new
11
-
12
- task default: %i[spec rubocop]
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securerandom"
4
-
5
- require_relative "./shared"
6
-
7
- RSpec.describe "Apple", :vcr do
8
- let(:provider) { :apple }
9
- let(:username) { ENV.fetch("APPLE_USERNAME") }
10
- let(:password) { ENV.fetch("APPLE_PASSWORD") }
11
- let(:credentials) { Calendav.credentials(provider, username, password) }
12
- let(:host) { "https://p49-caldav.icloud.com/20264203208/calendars/" }
13
-
14
- subject { Calendav.client(credentials) }
15
-
16
- it "determines the user's principal URL" do
17
- expect(subject.principal_url)
18
- .to eq_encoded_url("https://caldav.icloud.com/20264203208/principal/")
19
- end
20
-
21
- it "determines the user's calendar URL" do
22
- expect(subject.calendars.home_url)
23
- .to eq_encoded_url("https://p49-caldav.icloud.com/20264203208/calendars/")
24
- end
25
-
26
- it_behaves_like "supporting calendar management"
27
-
28
- context "with a calendar" do
29
- let(:calendar_url) do
30
- subject.calendars.create(@name, display_name: "Calendav Test")
31
- end
32
- let(:calendar) { subject.calendars.find(calendar_url) }
33
-
34
- before :each do |example|
35
- @name = Digest::MD5.hexdigest(example.metadata[:full_description])
36
- end
37
-
38
- after :each do
39
- subject.calendars.delete(calendar.url)
40
- end
41
-
42
- it_behaves_like "supporting event management"
43
- it_behaves_like "supporting event deletion with etags"
44
- end
45
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "google/apis/calendar_v3"
4
- require "googleauth"
5
- require "icalendar"
6
- require "securerandom"
7
- require "uri"
8
-
9
- require_relative "./shared"
10
-
11
- RSpec.describe "Google", :vcr do
12
- let(:provider) { :google }
13
- let(:username) { ENV.fetch("GOOGLE_USERNAME") }
14
- let(:access_token) { @access_token }
15
- let(:credentials) { Calendav.credentials(provider, username, access_token) }
16
- let(:google_auth) { @google_auth }
17
-
18
- subject { Calendav.client(credentials) }
19
-
20
- before :each do
21
- @google_auth = Google::Auth::UserRefreshCredentials.new(
22
- client_id: ENV.fetch("GOOGLE_CLIENT_ID"),
23
- scope: [],
24
- client_secret: ENV.fetch("GOOGLE_CLIENT_SECRET"),
25
- refresh_token: ENV.fetch("GOOGLE_REFRESH_TOKEN"),
26
- additional_parameters: { "access_type" => "offline" }
27
- )
28
-
29
- @access_token = begin
30
- @google_auth.fetch_access_token!
31
- @google_auth.access_token
32
- end
33
- end
34
-
35
- it "determines the user's principal URL" do
36
- expect(subject.principal_url).to eq_encoded_url(
37
- "https://apidata.googleusercontent.com/caldav/v2/#{username}/user"
38
- )
39
- end
40
-
41
- it "determines the user's calendar URL" do
42
- expect(subject.calendars.home_url).to eq_encoded_url(
43
- "https://apidata.googleusercontent.com/caldav/v2/#{username}/"
44
- )
45
- end
46
-
47
- it "cannot create calendars" do
48
- expect(subject.calendars.create?).to eq(false)
49
- end
50
-
51
- it "can find and update calendars" do
52
- calendars = subject.calendars.list
53
- calendar = calendars.detect { |cal| cal.display_name == "Calendav Test" }
54
-
55
- expect(calendar).to_not be_nil
56
-
57
- subject.calendars.update(calendar.url, display_name: "Calendav Update")
58
-
59
- calendars = subject.calendars.list
60
- calendar = calendars.detect { |cal| cal.display_name == "Calendav Update" }
61
-
62
- subject.calendars.update(calendar.url, display_name: "Calendav Test")
63
- end
64
-
65
- context "with a calendar" do
66
- let(:calendars) { subject.calendars.list }
67
- let(:calendar) { calendars.detect { |cal| cal.display_name == name } }
68
- let(:name) { "Calendav Test #{Time.now.to_i}" }
69
- let(:service) { Google::Apis::CalendarV3::CalendarService.new }
70
- let(:entry) { Google::Apis::CalendarV3::Calendar.new(summary: name) }
71
-
72
- before :each do
73
- service.authorization = google_auth
74
-
75
- result = service.insert_calendar entry
76
- entry.update!(**result.to_h)
77
- end
78
-
79
- after :each do
80
- service.delete_calendar entry.id
81
- end
82
-
83
- it_behaves_like "supporting event management"
84
-
85
- it "does not respect etag conditions for deletions" do
86
- event_url = subject.events.create(
87
- calendar.url, "calendav-event.ics", ical_event("Brunch", 10, 30)
88
- )
89
- event = subject.events.find(event_url)
90
-
91
- expect(
92
- subject.events.update(
93
- event_url, update_summary(event, "Coffee"), etag: event.etag
94
- )
95
- ).to eq(true)
96
-
97
- # Google doesn't care about the If-Match header on DELETE requests :(
98
- expect(subject.events.delete(event_url, etag: event.etag)).to eq(true)
99
- end
100
- end
101
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securerandom"
4
-
5
- require_relative "./shared"
6
-
7
- RSpec.describe "Radicale" do
8
- let(:provider) { :radicale }
9
- let(:username) { ENV.fetch("RADICALE_USERNAME") }
10
- let(:password) { ENV.fetch("RADICALE_PASSWORD") }
11
- let(:host) { ENV.fetch("RADICALE_HOST") }
12
- let(:credentials) do
13
- Calendav::Credentials::Standard.new(
14
- host: host,
15
- username: username,
16
- password: password,
17
- authentication: :basic_auth
18
- )
19
- end
20
-
21
- subject { Calendav.client(credentials) }
22
-
23
- it "determines the user's principal URL" do
24
- expect(subject.principal_url)
25
- .to eq_encoded_url("#{host}/test/")
26
- end
27
-
28
- it "determines the user's calendar URL" do
29
- expect(subject.calendars.home_url)
30
- .to eq_encoded_url("#{host}/test/")
31
- end
32
-
33
- it_behaves_like "supporting calendar management"
34
-
35
- context "with a calendar" do
36
- let(:calendar_url) do
37
- subject.calendars.create("calendav-test", display_name: "Calendav Test")
38
- end
39
- let(:calendar) { subject.calendars.find(calendar_url) }
40
-
41
- after :each do
42
- subject.calendars.delete(calendar.url)
43
- end
44
-
45
- it_behaves_like "supporting event management"
46
- it_behaves_like "supporting event deletion with etags"
47
- end
48
- end
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "icalendar"
4
- require "icalendar/tzinfo"
5
- require "securerandom"
6
- require "uri"
7
-
8
- RSpec.shared_examples "supporting calendar management" do
9
- it "supports calendar creation" do
10
- expect(subject.calendars.create?).to eq(true)
11
- end
12
-
13
- it "can create, find, update and delete calendars" do
14
- identifier = "calendav-test"
15
- time_zone = TZInfo::Timezone.get "UTC"
16
- ical_time_zone = time_zone.ical_timezone Time.now.utc
17
-
18
- url = subject.calendars.create(
19
- identifier,
20
- display_name: "Calendav Test",
21
- description: "For test purposes only",
22
- color: "#00FF00",
23
- time_zone: ical_time_zone.to_ical
24
- )
25
- expect(url).to include(URI.decode_www_form_component(identifier))
26
- expect(url).to start_with(host)
27
-
28
- calendars = subject.calendars.list
29
- expect(calendars.collect(&:display_name)).to include("Calendav Test")
30
-
31
- expect(
32
- subject.calendars.update(url, display_name: "Calendav Update")
33
- ).to eq(true)
34
-
35
- calendars = subject.calendars.list
36
- expect(calendars.collect(&:display_name)).to include("Calendav Update")
37
-
38
- subject.calendars.delete(url)
39
- end
40
- end
41
-
42
- RSpec.shared_examples "supporting event management" do
43
- it "supports events" do
44
- expect(calendar.components).to include("VEVENT")
45
- end
46
-
47
- it "supports WebDAV-Sync" do
48
- expect(calendar.reports).to include("sync-collection")
49
- end
50
-
51
- it "can create, find, update and delete events" do
52
- # Create an event
53
- event_url = subject.events.create(
54
- calendar.url, "calendav-event-1.ics", ical_event("Brunch", 10, 30)
55
- )
56
- expect(event_url).to include(URI.decode_www_form_component(calendar.url))
57
- event = subject.events.find(event_url)
58
-
59
- # Search for the event
60
- events = subject.events.list(
61
- calendar.url, from: time_at(0, 0), to: time_at(23, 59)
62
- )
63
- expect(events.length).to eq(1)
64
- expect(events.first.summary).to eq("Brunch")
65
- expect(events.first.dtstart.to_time).to eq(time_at(10, 30))
66
- expect(events.first.url).to eq_encoded_url(event_url)
67
-
68
- # Update the event
69
- subject.events.update(event_url, update_summary(event, "Coffee"))
70
-
71
- # Search again
72
- events = subject.events.list(
73
- calendar.url, from: time_at(0, 0), to: time_at(23, 59)
74
- )
75
- expect(events.length).to eq(1)
76
- expect(events.first.summary).to eq("Coffee")
77
- expect(events.first.dtstart.to_time).to eq(time_at(10, 30))
78
- expect(events.first.url).to eq_encoded_url(event_url)
79
-
80
- # Create another event
81
- another_url = subject.events.create(
82
- calendar.url, "calendav-event-2.ics", ical_event("Brunch", 10, 30)
83
- )
84
-
85
- # Search for all events
86
- events = subject.events.list(calendar.url)
87
- expect(events.length).to eq(2)
88
-
89
- # Delete the events
90
- expect(subject.events.delete(event_url)).to eq(true)
91
- expect(subject.events.delete(another_url)).to eq(true)
92
- end
93
-
94
- it "respects etag conditions with updates" do
95
- event_url = subject.events.create(
96
- calendar.url, "calendav-event.ics", ical_event("Brunch", 10, 30)
97
- )
98
- event = subject.events.find(event_url)
99
-
100
- expect(
101
- subject.events.update(
102
- event_url, update_summary(event, "Coffee"), etag: event.etag
103
- )
104
- ).to eq(true)
105
-
106
- expect(subject.events.find(event_url).summary).to eq("Coffee")
107
-
108
- # Wait for server to catch up
109
- sleep 1
110
-
111
- # Updating with the old etag should fail
112
- expect(
113
- subject.events.update(
114
- event_url, update_summary(event, "Brunch"), etag: event.etag
115
- )
116
- ).to eq(false)
117
-
118
- expect(subject.events.find(event_url).summary).to eq("Coffee")
119
-
120
- expect(subject.events.delete(event_url)).to eq(true)
121
- end
122
-
123
- it "handles synchronisation requests" do
124
- first_url = subject.events.create(
125
- calendar.url, "calendav-event-1.ics", ical_event("Brunch", 10, 30)
126
- )
127
- first = subject.events.find(first_url)
128
- token = subject.calendars.find(calendar.url, sync: true).sync_token
129
-
130
- events = subject.events.list(calendar.url)
131
- expect(events.length).to eq(1)
132
-
133
- second_url = subject.events.create(
134
- calendar.url, "calendav-event-2.ics", ical_event("Brunch Again", 11, 30)
135
- )
136
-
137
- subject.events.update(first_url, update_summary(first, "Coffee"))
138
- first = subject.events.find(first_url)
139
-
140
- collection = subject.calendars.sync(calendar.url, token)
141
- expect(collection.changes.collect(&:url))
142
- .to match_encoded_urls([first_url, second_url])
143
-
144
- expect(collection.deletions).to be_empty
145
- expect(collection.more?).to eq(false)
146
-
147
- subject.events.update(first_url, update_summary(first, "Brunch"))
148
- subject.events.delete(second_url)
149
-
150
- collection = subject.calendars.sync(calendar.url, collection.sync_token)
151
- urls = collection.changes.collect(&:url)
152
- expect(urls.length).to eq(1)
153
- expect(urls[0]).to eq_encoded_url(first_url)
154
-
155
- expect(collection.deletions.length).to eq(1)
156
- expect(collection.deletions.first).to eq_encoded_url(second_url)
157
- expect(collection.more?).to eq(false)
158
-
159
- subject.events.delete(first_url)
160
- end
161
- end
162
-
163
- RSpec.shared_examples "supporting event deletion with etags" do
164
- it "respects etag conditions with deletions" do
165
- event_url = subject.events.create(
166
- calendar.url, "calendav-event.ics", ical_event("Brunch", 10, 30)
167
- )
168
- event = subject.events.find(event_url)
169
-
170
- expect(
171
- subject.events.update(
172
- event_url, update_summary(event, "Coffee"), etag: event.etag
173
- )
174
- ).to eq(true)
175
- expect(subject.events.find(event_url).summary).to eq("Coffee")
176
-
177
- expect(subject.events.delete(event_url, etag: event.etag)).to eq(false)
178
- expect(subject.events.delete(event_url)).to eq(true)
179
- end
180
- end
@@ -1,10 +0,0 @@
1
- [auth]
2
- type = htpasswd
3
- htpasswd_filename = /var/radicale/users
4
- htpasswd_encryption = bcrypt
5
-
6
- [server]
7
- hosts = 0.0.0.0:8000
8
-
9
- [storage]
10
- filesystem_folder = /var/radicale/collections
@@ -1 +0,0 @@
1
- test:$2y$05$O.Z0365vM0GOv.YN1WlIEOnd0gaGEB/SmoRiSjIHnstXIm6ZURl/y
data/spec/spec_helper.rb DELETED
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "calendav"
4
- require "dotenv"
5
-
6
- Dotenv.load
7
-
8
- require_relative "support/encoded_matchers"
9
- require_relative "support/event_helpers"
10
- require_relative "support/vcr"
11
-
12
- RSpec.configure do |config|
13
- config.disable_monkey_patching!
14
-
15
- config.expect_with :rspec do |c|
16
- c.syntax = :expect
17
- end
18
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EncodedMatchers
4
- def eq_encoded_url(expected)
5
- eq(RecodeURI.call(expected))
6
- end
7
-
8
- def match_encoded_urls(expected)
9
- match_array(expected.collect { |uri| RecodeURI.call(uri) })
10
- end
11
- end
12
-
13
- class RecodeURI
14
- def self.call(uri)
15
- encoded = URI(uri)
16
-
17
- encoded.path = encoded.path.split("/").collect do |piece|
18
- URI.encode_www_form_component(piece)
19
- end.join("/")
20
-
21
- encoded.path += "/" if uri.end_with?("/")
22
-
23
- encoded.to_s
24
- end
25
- end
26
-
27
- RSpec.configure do |config|
28
- config.include EncodedMatchers
29
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # require "active_support"
4
- require "icalendar"
5
- require "securerandom"
6
-
7
- module EventHelpers
8
- def ical_event(summary, hour, minute)
9
- start = time_at(hour, minute)
10
-
11
- ics = Icalendar::Calendar.new
12
-
13
- ics.event do |event|
14
- event.dtstart = start
15
- event.dtend = start + 3600
16
- event.summary = summary
17
- end
18
-
19
- ics.tap(&:publish).to_ical
20
- end
21
-
22
- def time_at(hour, minute = 0)
23
- now = Time.now
24
-
25
- Time.utc(now.year, now.month, now.day, hour, minute)
26
- end
27
-
28
- def update_summary(event, summary)
29
- ics = Icalendar::Calendar.parse(event.calendar_data).first
30
-
31
- ics.events.first.summary = summary
32
-
33
- ics.to_ical
34
- end
35
- end
36
-
37
- RSpec.configure do |config|
38
- config.include EventHelpers
39
- end
data/spec/support/vcr.rb DELETED
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "timecop"
4
- require "webmock/rspec"
5
- require "vcr"
6
- require "vcr_assistant/rspec"
7
-
8
- VCR.configure do |config|
9
- config.cassette_library_dir = File.expand_path(
10
- File.join(__dir__, "../cassettes")
11
- )
12
- config.hook_into :webmock
13
- config.ignore_hosts "127.0.0.1"
14
- end
15
-
16
- RSpec.configure do |config|
17
- config.around(:each, :vcr) do |example|
18
- assisted_cassette(example) do |_assistant|
19
- Timecop.freeze(Time.gm(2022))
20
-
21
- example.run
22
-
23
- Timecop.return
24
- end
25
- end
26
- end