google_calendar 0.6.2 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,4 +1,7 @@
1
1
  ---
2
+ SHA1:
3
+ metadata.gz: 7566afbd7d0c1b5157f8e015004b178fed446e88
4
+ data.tar.gz: 9101a5db3d4daf55e78ae1aa38e56a336b372f66
2
5
  SHA512:
3
- metadata.gz: 37b7d1c2914d9c4975ff8477a94a5c5ae18d5cb8dacf089bbadb1a16414984adc4b606a97a08f52b9baae9beb018344c6cf6616f65d1064d4c5499d7ddc494a9
4
- data.tar.gz: be2f3af778d82be79cebfac47135c2441363eeeffeed43d7eab04a3935f192b287fcc79b9b55b3bd02ccb6beac58eaf33c75db9d2a947efe42aadf64e106a25b
6
+ metadata.gz: 75e132c4aabfc403960480fde10ed08a5534be9ddbdb4bfc4a026b89f59441cf10e76c5b44db5f389715348a5fdcf6140ebbe7a068536bdd521b7e52e01ec702
7
+ data.tar.gz: 977c123de8e964c0bce1d8ac390f23e2f95b39241b23144606b053215bbbf8ee38ed01e61c1d382f4c487b5fe35db8b940f629c2d8f84dffe68994a7dc03ffea
@@ -1,15 +1,14 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.1"
4
- - "2.2"
5
- - "2.3"
6
- - "2.4"
7
- before_install:
8
- - gem install bundler
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
9
8
  addons:
10
9
  code_climate:
11
10
  repo_token: 35bb9d218078742d37436a9c9a8b78199e8c7312d034081881de670e95b8dcad
12
11
  after_success:
13
12
  - bundle exec codeclimate-test-reporter
14
13
  # uncomment this line if your project needs to run something other than `rake`:
15
- # script: bundle exec rspec spec
14
+ # script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Using google_calendar to manage dependencies
4
4
  gemspec
@@ -1,60 +1,60 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- google_calendar (0.6.1)
5
- TimezoneParser (~> 0.2.0)
6
- json (>= 1.8.3, < 2.1)
4
+ google_calendar (0.6.2)
5
+ TimezoneParser (~> 0.3.0)
6
+ json (>= 1.8.3)
7
7
  signet (~> 0.7)
8
8
 
9
9
  GEM
10
- remote: http://rubygems.org/
10
+ remote: https://rubygems.org/
11
11
  specs:
12
- TimezoneParser (0.2.0)
12
+ TimezoneParser (0.3.2)
13
13
  insensitive_hash
14
14
  tzinfo
15
- addressable (2.5.0)
16
- public_suffix (~> 2.0, >= 2.0.2)
15
+ addressable (2.5.2)
16
+ public_suffix (>= 2.0.2, < 4.0)
17
17
  ansi (1.5.0)
18
18
  builder (3.2.3)
19
- codeclimate-test-reporter (1.0.5)
20
- simplecov
19
+ codeclimate-test-reporter (1.0.8)
20
+ simplecov (<= 0.13)
21
21
  docile (1.1.5)
22
- dotenv (2.2.0)
23
- faraday (0.11.0)
22
+ dotenv (2.2.1)
23
+ faraday (0.14.0)
24
24
  multipart-post (>= 1.2, < 3)
25
25
  insensitive_hash (0.3.3)
26
- json (2.0.3)
27
- jwt (1.5.6)
26
+ json (2.1.0)
27
+ jwt (2.1.0)
28
28
  metaclass (0.0.4)
29
- minitest (5.10.1)
30
- minitest-reporters (1.1.14)
29
+ minitest (5.11.3)
30
+ minitest-reporters (1.2.0)
31
31
  ansi
32
32
  builder
33
33
  minitest (>= 5.0)
34
34
  ruby-progressbar
35
- mocha (1.2.1)
35
+ mocha (1.4.0)
36
36
  metaclass (~> 0.0.1)
37
- multi_json (1.12.1)
37
+ multi_json (1.13.1)
38
38
  multipart-post (2.0.0)
39
- public_suffix (2.0.5)
40
- rake (11.3.0)
41
- rb-fsevent (0.9.8)
42
- rdoc (4.3.0)
43
- ruby-progressbar (1.8.1)
39
+ public_suffix (3.0.2)
40
+ rake (12.3.1)
41
+ rb-fsevent (0.10.3)
42
+ rdoc (5.1.0)
43
+ ruby-progressbar (1.9.0)
44
44
  shoulda-context (1.2.2)
45
- signet (0.7.3)
45
+ signet (0.8.1)
46
46
  addressable (~> 2.3)
47
47
  faraday (~> 0.9)
48
- jwt (~> 1.5)
48
+ jwt (>= 1.5, < 3.0)
49
49
  multi_json (~> 1.10)
50
50
  simplecov (0.13.0)
51
51
  docile (~> 1.1.0)
52
52
  json (>= 1.8, < 3)
53
53
  simplecov-html (~> 0.10.0)
54
- simplecov-html (0.10.0)
54
+ simplecov-html (0.10.2)
55
55
  terminal-notifier-guard (1.7.0)
56
- thread_safe (0.3.5)
57
- tzinfo (1.2.2)
56
+ thread_safe (0.3.6)
57
+ tzinfo (1.2.5)
58
58
  thread_safe (~> 0.1)
59
59
 
60
60
  PLATFORMS
@@ -66,13 +66,13 @@ DEPENDENCIES
66
66
  dotenv (~> 2.1)
67
67
  google_calendar!
68
68
  minitest (~> 5.1)
69
- minitest-reporters (~> 1.0)
70
- mocha (~> 1.1)
71
- rake (~> 11)
69
+ minitest-reporters (~> 1.2)
70
+ mocha (~> 1.4)
71
+ rake (>= 11)
72
72
  rb-fsevent (~> 0.9)
73
- rdoc (~> 4.1)
73
+ rdoc (>= 4.1)
74
74
  shoulda-context (~> 1.2)
75
75
  terminal-notifier-guard (~> 1.6)
76
76
 
77
77
  BUNDLED WITH
78
- 1.14.4
78
+ 1.16.1
@@ -11,13 +11,15 @@ A fast lightweight and minimalist wrapper around the {Google Calendar}[https://w
11
11
  <b>Obtain a Client ID and Secret</b>
12
12
 
13
13
  1. Go to the {Google Developers Console}[https://console.developers.google.com/].
14
- 1. Select a project, or create a new one.
15
- 1. In the sidebar on the left, expand APIs & auth. Next, click APIs. In the list of APIs, make sure the status is ON for the Calendar API.
14
+ 1. Select a project, or create a new one (at the top of the page).
15
+ 1. In the sidebar on the left, select Library.
16
+ 1. Type in 'Google Calendar' in the search box and click on 'Google Calendar API' in the results.
17
+ 1. Click on the 'Enable' link at the top of the page.
16
18
  1. In the sidebar on the left, select Credentials.
17
- 1. In either case, you end up on the Credentials page and can create your project's credentials from here.
18
- 1. If you haven't done so already, create your OAuth 2.0 credentials by clicking Create new Client ID under the OAuth heading. Next, look for your application's client ID and client secret in the relevant table. You may also create and edit redirect URIs from this page.
19
+ 1. If you haven't done so already, create your 'OAuth client ID' by clicking Create Credentials'. Note: you need to set your 'Product name show to users' on the OAuth consent screen before you can create your client ID.
20
+ 1. Select the 'Other' option and click create.
19
21
 
20
- <em>Take note of the Client ID as you'll need to add it to your code later.</em>
22
+ <em>Take note of the Client ID and Client Secret as you'll need to add it to your code later.</em>
21
23
 
22
24
  <b>Find your calendar ID</b>
23
25
 
@@ -111,7 +113,7 @@ to +.env+ for use by Dotenv. You can also use +.env.default+ as your
111
113
  own starting point, just remember to copy it over to +.env+ before
112
114
  running tests.
113
115
 
114
- You can modify +.env+ with your own credentials and not worry about
116
+ You can modify +.env+ with your own credentials and don't worry about
115
117
  accidentally committing to the repo as +.env+ is in the +.gitignore+.
116
118
 
117
119
  == Copyright
@@ -2,8 +2,8 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "google_calendar"
5
- s.version = "0.6.2"
6
- s.date = "2017-02-17"
5
+ s.version = "0.6.4"
6
+ s.date = "2018-03-23"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
9
 
@@ -24,21 +24,21 @@ Gem::Specification.new do |s|
24
24
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
25
 
26
26
  s.require_paths = ["lib"]
27
- s.rubygems_version = "2.6.10"
27
+ s.rubygems_version = "2.6.14"
28
28
 
29
29
  s.add_runtime_dependency(%q<signet>, ["~> 0.7"])
30
- s.add_runtime_dependency(%q<json>, [">= 1.8.3", "< 2.1"])
31
- s.add_runtime_dependency(%q<TimezoneParser>, ["~> 0.2.0"])
30
+ s.add_runtime_dependency(%q<json>, [">= 1.8.3"])
31
+ s.add_runtime_dependency(%q<TimezoneParser>, ["~> 0.3.0"])
32
32
 
33
33
  s.add_development_dependency(%q<terminal-notifier-guard>, ["~> 1.6"])
34
34
  s.add_development_dependency(%q<rb-fsevent>, ["~> 0.9"])
35
35
  s.add_development_dependency(%q<minitest>, ["~> 5.1"])
36
- s.add_development_dependency(%q<minitest-reporters>, ["~> 1.0"])
36
+ s.add_development_dependency(%q<minitest-reporters>, ["~> 1.2"])
37
37
  s.add_development_dependency(%q<shoulda-context>, ["~> 1.2"])
38
38
  s.add_development_dependency(%q<bundler>, [">= 1.2"])
39
- s.add_development_dependency(%q<mocha>, ["~> 1.1"])
40
- s.add_development_dependency(%q<rake>, ["~> 11"])
41
- s.add_development_dependency(%q<rdoc>, ["~> 4.1"])
39
+ s.add_development_dependency(%q<mocha>, ["~> 1.4"])
40
+ s.add_development_dependency(%q<rake>, [">= 11"])
41
+ s.add_development_dependency(%q<rdoc>, [">= 4.1"])
42
42
  s.add_development_dependency(%q<dotenv>, ["~> 2.1"])
43
43
 
44
44
  end
@@ -6,7 +6,7 @@ module Google
6
6
  #
7
7
  class Calendar
8
8
 
9
- attr_reader :id, :connection, :summary
9
+ attr_reader :id, :connection, :summary, :location, :description, :time_zone
10
10
 
11
11
  #
12
12
  # Setup and connect to the specified Google Calendar.
@@ -14,7 +14,7 @@ module Google
14
14
  # * :client_id => the client ID that you received from Google after registering your application with them (https://console.developers.google.com/). REQUIRED
15
15
  # * :client_secret => the client secret you received from Google after registering your application with them. REQUIRED
16
16
  # * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars. Use 'urn:ietf:wg:oauth:2.0:oob' if you are using an 'application'" REQUIRED
17
- # * :calendar_id => the id of the calendar you would like to work with (see Readme.rdoc for instructions on how to find yours)
17
+ # * :calendar => the id of the calendar you would like to work with (see Readme.rdoc for instructions on how to find yours). REQUIRED
18
18
  # * :refresh_token => if a user has already given you access to their calendars, you can specify their refresh token here and you will be 'logged on' automatically (i.e. they don't need to authorize access again). OPTIONAL
19
19
  #
20
20
  # See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
@@ -37,7 +37,10 @@ module Google
37
37
  # * :client_id => the client ID that you received from Google after registering your application with them (https://console.developers.google.com/). REQUIRED
38
38
  # * :client_secret => the client secret you received from Google after registering your application with them. REQUIRED
39
39
  # * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars. Use 'urn:ietf:wg:oauth:2.0:oob' if you are using an 'application'" REQUIRED
40
- # * :summary => title of the calendar being created.
40
+ # * :summary => title of the calendar being created. OPTIONAL
41
+ # * :location => geographic location of the calendar as free-form text. OPTIONAL
42
+ # * :time_zone => the time zone of the calendar. (Formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich".) OPTIONAL
43
+ # * :description => description of the calendar. OPTIONAL
41
44
  # * :refresh_token => if a user has already given you access to their calendars, you can specify their refresh token here and you will be 'logged on' automatically (i.e. they don't need to authorize access again). OPTIONAL
42
45
  #
43
46
  # See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
@@ -47,16 +50,98 @@ module Google
47
50
  # :client_id => YOUR_CLIENT_ID,
48
51
  # :client_secret => YOUR_SECRET,
49
52
  # :summary => 'Test Calendar',
53
+ # :location => 'Somewhere',
54
+ # :description => 'Test Calendar Description',
55
+ # :time_zone => 'Europe/Zurich',
50
56
  # :redirect_url => "urn:ietf:wg:oauth:2.0:oob" # this is what Google uses for 'applications'
51
57
  # )
52
58
  #
53
59
  def self.create(params={}, connection=nil)
54
60
  cal = new(params, connection)
55
61
  cal.instance_variable_set(:@summary, params[:summary])
62
+ cal.instance_variable_set(:@location, params[:location])
63
+ cal.instance_variable_set(:@description, params[:description])
64
+ cal.instance_variable_set(:@time_zone, params[:time_zone])
56
65
 
57
66
  cal.save
58
67
  end
59
68
 
69
+ #
70
+ # Connect and retrieve a Google Calendar.
71
+ # the +params+ paramater accepts
72
+ # * :client_id => the client ID that you received from Google after registering your application with them (https://console.developers.google.com/). REQUIRED
73
+ # * :client_secret => the client secret you received from Google after registering your application with them. REQUIRED
74
+ # * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars. Use 'urn:ietf:wg:oauth:2.0:oob' if you are using an 'application'" REQUIRED
75
+ # * :calendar => the id of the calendar you would like to work with (see Readme.rdoc for instructions on how to find yours). REQUIRED
76
+ # * :refresh_token => if a user has already given you access to their calendars, you can specify their refresh token here and you will be 'logged on' automatically (i.e. they don't need to authorize access again). OPTIONAL
77
+ #
78
+ # See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
79
+ #
80
+ # ==== Example
81
+ # Google::Calendar.get(
82
+ # :client_id => YOUR_CLIENT_ID,
83
+ # :client_secret => YOUR_SECRET,
84
+ # :calendar => YOUR_CALENDAR_ID,
85
+ # :redirect_url => "urn:ietf:wg:oauth:2.0:oob" # this is what Google uses for 'applications'
86
+ # )
87
+ #
88
+ def self.get(params={}, connection=nil)
89
+ cal = new(params, connection)
90
+ cal.retrieve_calendar
91
+ end
92
+
93
+ #
94
+ # Connect and update a Google Calendar.
95
+ # the +params+ paramater accepts
96
+ # * :summary => title of the calendar being created. OPTIONAL
97
+ # * :location => geographic location of the calendar as free-form text. OPTIONAL
98
+ # * :time_zone => the time zone of the calendar. (Formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich".) OPTIONAL
99
+ # * :description => description of the calendar. OPTIONAL
100
+ # * :refresh_token => if a user has already given you access to their calendars, you can specify their refresh token here and you will be 'logged on' automatically (i.e. they don't need to authorize access again). OPTIONAL
101
+ #
102
+ # See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
103
+ #
104
+ # ==== Example
105
+ # google_calendar_object.update(
106
+ # :summary => 'Test Calendar',
107
+ # :location => 'Somewhere',
108
+ # :description => 'Test Calendar Description',
109
+ # :time_zone => 'Europe/Zurich',
110
+ # )
111
+ #
112
+ def update(params={})
113
+ instance_variable_set(:@summary, params[:summary])
114
+ instance_variable_set(:@location, params[:location])
115
+ instance_variable_set(:@description, params[:description])
116
+ instance_variable_set(:@time_zone, params[:time_zone])
117
+
118
+ response =
119
+ send_calendar_request(
120
+ "/#{@id}",
121
+ :put,
122
+ {
123
+ summary: @summary,
124
+ location: @location,
125
+ description: @description,
126
+ timeZone: @time_zone,
127
+ }.to_json
128
+ )
129
+ @raw = JSON.parse(response.body)
130
+ self
131
+ end
132
+
133
+ #
134
+ # Destroy a Google Calendar.
135
+ #
136
+ # See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
137
+ #
138
+ # ==== Example
139
+ # google_calendar_object.destroy
140
+ #
141
+ def destroy
142
+ send_calendar_request("/#{@id}", :delete)
143
+ end
144
+
60
145
  #
61
146
  # The URL you need to send a user in order to let them grant you access to their calendars.
62
147
  #
@@ -105,10 +190,27 @@ module Google
105
190
  # the calendar that was saved.
106
191
  #
107
192
  def save
108
- response = send_calendar_request("/", :post, {:summary => @summary}.to_json)
193
+ response = send_calendar_request("/", :post, {:summary => @summary}.to_json)
109
194
  update_after_save(response)
110
195
  end
111
196
 
197
+ #
198
+ # Get an existing calender.
199
+ # Returns:
200
+ # the calendar that was requested.
201
+ #
202
+ def retrieve_calendar
203
+ response = send_calendar_request("/#{@id}", :get)
204
+ @raw = JSON.parse(response.body)
205
+ instance_variable_set(:@summary, @raw['summary'])
206
+ instance_variable_set(:@location, @raw['location'])
207
+ instance_variable_set(:@description, @raw['description'])
208
+ instance_variable_set(:@time_zone, @raw['timeZone'])
209
+ @html_link = @raw['htmlLink']
210
+
211
+ self
212
+ end
213
+
112
214
  #
113
215
  # Find all of the events associated with this calendar.
114
216
  # Returns:
@@ -269,8 +371,10 @@ module Google
269
371
  # If the event is no longer on the server it creates a new one with the specified values.
270
372
  # Works like the create_event method.
271
373
  #
272
- def find_or_create_event_by_id(id, &blk)
273
- if id && event = find_event_by_id(id)[0]
374
+ def find_or_create_event_by_id(id, &blk)
375
+ event = id ? find_event_by_id(id)[0] : nil
376
+
377
+ if event
274
378
  setup_event(event, &blk)
275
379
  elsif id
276
380
  event = Event.new(id: id, new_event_with_id_specified: true)
@@ -290,12 +394,12 @@ module Google
290
394
  body = event.use_quickadd? ? nil : event.to_json
291
395
  notifications = "sendNotifications=#{event.send_notifications?}"
292
396
  query_string = if event.use_quickadd?
293
- "/quickAdd?#{notifications}&text=#{event.title}"
294
- elsif event.new_event?
295
- "?#{notifications}"
296
- else # update existing event.
297
- "/#{event.id}?#{notifications}"
298
- end
397
+ "/quickAdd?#{notifications}&text=#{event.title}"
398
+ elsif event.new_event?
399
+ "?#{notifications}"
400
+ else # update existing event.
401
+ "/#{event.id}?#{notifications}"
402
+ end
299
403
 
300
404
  send_events_request(query_string, method, body)
301
405
  end
@@ -153,15 +153,33 @@ module Google
153
153
 
154
154
  #
155
155
  # Check for common HTTP Errors and raise the appropriate response.
156
+ # Note: error 401 (InvalidCredentialsError) is handled by Signet.
156
157
  #
157
158
  def check_for_errors(response) #:nodoc
158
159
  case response.status
159
160
  when 400 then raise HTTPRequestFailed, response.body
161
+ when 403 then parse_403_error(response)
160
162
  when 404 then raise HTTPNotFound, response.body
163
+ when 409 then raise RequestedIdentifierAlreadyExistsError, response.body
164
+ when 410 then raise GoneError, response.body
165
+ when 412 then raise PreconditionFailedError, response.body
166
+ when 500 then raise BackendError, response.body
161
167
  end
162
168
  end
163
169
 
164
- private
170
+ #
171
+ # Utility method to centralize handling of 403 errors.
172
+ #
173
+ def parse_403_error(response)
174
+ case JSON.parse(response.body)["error"]["message"]
175
+ when "Forbidden" then raise ForbiddenError, response.body
176
+ when "Daily Limit Exceeded" then raise DailyLimitExceededError, response.body
177
+ when "User Rate Limit Exceeded" then raise UserRateLimitExceededError, response.body
178
+ when "Rate Limit Exceeded" then raise RateLimitExceededError, response.body
179
+ when "Calendar usage limits exceeded." then raise CalendarUsageLimitExceededError, response.body
180
+ else raise ForbiddenError, response.body
181
+ end
182
+ end
165
183
 
166
184
  #
167
185
  # Utility method to centralize credential validation.
@@ -1,8 +1,78 @@
1
1
  module Google
2
- class HTTPRequestFailed < StandardError; end
2
+ # Signet::AuthorizationError
3
+ # Not part of Google Calendar API Errors
3
4
  class HTTPAuthorizationFailed < StandardError; end
5
+
6
+ # Google Calendar API Errors per documentation
7
+ # https://developers.google.com/google-apps/calendar/v3/errors
8
+
9
+ # 400: Bad Request
10
+ #
11
+ # User error. This can mean that a required field or parameter has not been
12
+ # provided, the value supplied is invalid, or the combination of provided
13
+ # fields is invalid.
14
+ class HTTPRequestFailed < StandardError; end
15
+
16
+ # 401: Invalid Credentials
17
+ #
18
+ # Invalid authorization header. The access token you're using is either
19
+ # expired or invalid.
20
+ class InvalidCredentialsError < StandardError; end
21
+
22
+ # 403: Daily Limit Exceeded
23
+ #
24
+ # The Courtesy API limit for your project has been reached.
25
+ class DailyLimitExceededError < StandardError; end
26
+
27
+ # 403: User Rate Limit Exceeded
28
+ #
29
+ # The per-user limit from the Developer Console has been reached.
30
+ class UserRateLimitExceededError < StandardError; end
31
+
32
+ # 403: Rate Limit Exceeded
33
+ #
34
+ # The user has reached Google Calendar API's maximum request rate per
35
+ # calendar or per authenticated user.
36
+ class RateLimitExceededError < StandardError; end
37
+
38
+ # 403: Calendar usage limits exceeded
39
+ #
40
+ # The user reached one of the Google Calendar limits in place to protect
41
+ # Google users and infrastructure from abusive behavior.
42
+ class CalendarUsageLimitExceededError < StandardError; end
43
+
44
+ # 404: Not Found
45
+ #
46
+ # The specified resource was not found.
4
47
  class HTTPNotFound < StandardError; end
5
- class HTTPTooManyRedirections < StandardError; end
6
- class InvalidCalendar < StandardError; end
7
- class CalenarIDMissing < StandardError; end
48
+
49
+ # 409: The requested identifier already exists
50
+ #
51
+ # An instance with the given ID already exists in the storage.
52
+ class RequestedIdentifierAlreadyExistsError < StandardError; end
53
+
54
+ # 410: Gone
55
+ #
56
+ # SyncToken or updatedMin parameters are no longer valid. This error can also
57
+ # occur if a request attempts to delete an event that has already been
58
+ # deleted.
59
+ class GoneError < StandardError; end
60
+
61
+ # 412: Precondition Failed
62
+ #
63
+ # The etag supplied in the If-match header no longer corresponds to the
64
+ # current etag of the resource.
65
+ class PreconditionFailedError < StandardError; end
66
+
67
+ # 500: Backend Error
68
+ #
69
+ # An unexpected error occurred while processing the request.
70
+ class BackendError < StandardError; end
71
+
72
+ #
73
+ # 403: Forbidden Error
74
+ #
75
+ # User has no authority to conduct the requested operation on the resource.
76
+ # This is not a part of official Google Calendar API Errors documentation.
77
+ class ForbiddenError < StandardError; end
8
78
  end
@@ -120,7 +120,7 @@ module Google
120
120
  # Returns whether the Event is an all-day event, based on whether the event starts at the beginning and ends at the end of the day.
121
121
  #
122
122
  def all_day?
123
- time = (@start_time.is_a? String) ? Time.parse(@start_time) : @start_time.dup.utc
123
+ time = (@start_time.is_a? String) ? Time.parse(@start_time) : @start_time.dup.utc
124
124
  duration % (24 * 60 * 60) == 0 && time == Time.local(time.year,time.month,time.day)
125
125
  end
126
126
 
@@ -314,7 +314,7 @@ module Google
314
314
  return {} unless @attendees
315
315
 
316
316
  attendees = @attendees.map do |attendee|
317
- attendee.select { |k,v| ['displayName', 'email', 'responseStatus'].include?(k) }
317
+ attendee.select { |k,_v| ['displayName', 'email', 'responseStatus'].include?(k) }
318
318
  end
319
319
 
320
320
  { "attendees" => attendees }
@@ -396,7 +396,7 @@ module Google
396
396
  def extended_properties_attributes
397
397
  return {} unless @extended_properties && (@extended_properties['shared'] || @extended_properties['private'])
398
398
 
399
- { "extendedProperties" => @extended_properties.select {|k,v| ['shared', 'private'].include?(k) } }
399
+ { "extendedProperties" => @extended_properties.select {|k,_v| ['shared', 'private'].include?(k) } }
400
400
  end
401
401
 
402
402
  #
@@ -0,0 +1,15 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "calendar",
6
+ "reason": "timeRangeEmpty",
7
+ "message": "The specified time range is empty.",
8
+ "locationType": "parameter",
9
+ "location": "timeMax",
10
+ }
11
+ ],
12
+ "code": 400,
13
+ "message": "The specified time range is empty."
14
+ }
15
+ }
@@ -1,15 +1,15 @@
1
1
  {
2
- "error": {
3
- "code": 401,
4
- "message": "Invalid Credentials",
5
- "errors": [
6
- {
7
- "locationType": "header",
8
- "domain": "global",
9
- "message": "Invalid Credentials",
10
- "reason": "authError",
11
- "location": "Authorization"
12
- }
13
- ]
14
- }
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "global",
6
+ "reason": "authError",
7
+ "message": "Invalid Credentials",
8
+ "locationType": "header",
9
+ "location": "Authorization",
10
+ }
11
+ ],
12
+ "code": 401,
13
+ "message": "Invalid Credentials"
14
+ }
15
15
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "message": "Calendar usage limits exceeded.",
7
+ "reason": "quotaExceeded"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "Calendar usage limits exceeded."
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "reason": "dailyLimitExceeded",
7
+ "message": "Daily Limit Exceeded"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "Daily Limit Exceeded"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "reason": "ForbiddenError",
7
+ "message": "Forbidden"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "Forbidden"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "reason": "rateLimitExceeded",
7
+ "message": "Rate Limit Exceeded"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "Rate Limit Exceeded"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "reason": "SomeRandomError",
7
+ "message": "RandomError"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "RandomError"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "usageLimits",
6
+ "reason": "userRateLimitExceeded",
7
+ "message": "User Rate Limit Exceeded"
8
+ }
9
+ ],
10
+ "code": 403,
11
+ "message": "User Rate Limit Exceeded"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "global",
6
+ "reason": "duplicate",
7
+ "message": "The requested identifier already exists."
8
+ }
9
+ ],
10
+ "code": 409,
11
+ "message": "The requested identifier already exists."
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "global",
6
+ "reason": "deleted",
7
+ "message": "Resource has been deleted"
8
+ }
9
+ ],
10
+ "code": 410,
11
+ "message": "Resource has been deleted"
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "global",
6
+ "reason": "conditionNotMet",
7
+ "message": "Precondition Failed",
8
+ "locationType": "header",
9
+ "location": "If-Match",
10
+ }
11
+ ],
12
+ "code": 412,
13
+ "message": "Precondition Failed"
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "error": {
3
+ "errors": [
4
+ {
5
+ "domain": "global",
6
+ "reason": "backendError",
7
+ "message": "Backend Error",
8
+ }
9
+ ],
10
+ "code": 500,
11
+ "message": "Backend Error"
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "kind": "calendar#calendar",
3
+ "etag": "\"W8S50vTLOjlc76YTrehSZVQwSEE/ai1KY6CkM6KpTpfYTn2jy_Z5fsc\"",
4
+ "id": "djg1ts9g20ih03ccb0fgsegkio@group.calendar.google.com",
5
+ "summary": "A New Calendar"
6
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "kind": "calendar#calendar",
3
+ "etag": "\"W8S50vTLOjlc76YTghtSZVQwSEE/cpIguMlgGWrAb4L_lleRpa2ALCA\"",
4
+ "id": "gqeb0i6v737kfu5md0f35htjlg@group.calendar.google.com",
5
+ "summary": "Some Calendar",
6
+ "description": "Our work events",
7
+ "location": "Portland",
8
+ "timeZone": "America/Los_Angeles"
9
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "kind": "calendar#calendar",
3
+ "etag": "\"W8S50vTLOjlc76YTghtSZVQwSEE/cpIguMlgGWrAb4L_lleRpa2ALCA\"",
4
+ "id": "gqeb0i6v737kfu5md0f35htjlg@group.calendar.google.com",
5
+ "summary": "Our Company",
6
+ "description": "Work event list"
7
+ }
@@ -13,6 +13,7 @@ class TestGoogleCalendar < Minitest::Test
13
13
  @refresh_token = ENV['REFRESH_TOKEN']
14
14
  @calendar_id = ENV['CALENDAR_ID']
15
15
  @access_token = ENV['ACCESS_TOKEN']
16
+ @redirect_url = "urn:ietf:wg:oauth:2.0:oob"
16
17
 
17
18
  @calendar = Calendar.new(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => ENV['REDIRECT_URL'], :refresh_token => @refresh_token, :calendar => @calendar_id)
18
19
 
@@ -27,24 +28,46 @@ class TestGoogleCalendar < Minitest::Test
27
28
  should "login with auth code" do
28
29
  @client_mock.stubs(:body).returns( get_mock_body("login_with_auth_code_success.json") )
29
30
  @calendar.login_with_auth_code('4/QzBU-n6GXnHUkorG0fiu6AhoZtIjW53qKLOREiJWFpQ.wn0UfiyaDlEfEnp6UAPFm0EazsV1kwI')
30
- assert_equal @calendar.auth_code, nil # the auth_code is discarded after it is used.
31
+ assert_nil @calendar.auth_code # the auth_code is discarded after it is used.
31
32
  assert_equal @calendar.access_token, @access_token
32
33
  assert_equal @calendar.refresh_token, '1/aJUy7pQzc4fUMX89BMMLeAfKcYteBKRMpQvf4fQFX0'
33
34
  end
34
35
 
35
36
  should "login with refresh token" do
36
37
  # no refresh_token specified
37
- cal = Calendar.new(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => "urn:ietf:wg:oauth:2.0:oob", :calendar => @calendar_id)
38
+ cal = Calendar.new(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => @redirect_url, :calendar => @calendar_id)
38
39
  @client_mock.stubs(:body).returns( get_mock_body("login_with_refresh_token_success.json") )
39
40
  cal.login_with_refresh_token(@refresh_token)
40
41
  assert_equal @calendar.access_token, @access_token
41
42
  end
42
43
 
44
+ should "login with get method" do
45
+ cal = Calendar.get(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => @redirect_url,
46
+ :calendar => @calendar_id, :refresh_token => @refresh_token)
47
+ @client_mock.stubs(:body).returns( get_mock_body("get_calendar.json") )
48
+ assert_equal cal.id, @calendar_id
49
+ end
50
+
51
+ should "update calendar" do
52
+ cal = Calendar.get(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => @redirect_url,
53
+ :calendar => @calendar_id, :refresh_token => @refresh_token)
54
+ @client_mock.stubs(:body).returns( get_mock_body("update_calendar.json") )
55
+ cal.update(:summary => 'Our Company', :description => "Work event list")
56
+ assert_equal @calendar.id, @calendar_id
57
+ end
58
+
59
+ should "create calendar" do
60
+ cal = Calendar.create(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => @redirect_url,
61
+ :refresh_token => @refresh_token, :summary => 'A New Calendar', :description => 'Our new calendar')
62
+ assert_equal cal.summary, 'A New Calendar'
63
+ end
64
+
43
65
  should "catch login with invalid credentials" do
44
66
  @client_mock.stubs(:status).returns(403)
45
67
  @client_mock.stubs(:body).returns( get_mock_body("403.json") )
46
68
  assert_raises(HTTPAuthorizationFailed) do
47
- Calendar.new(:client_id => 'abadid', :client_secret => 'abadsecret', :redirect_url => "urn:ietf:wg:oauth:2.0:oob", :refresh_token => @refresh_token, :calendar => @calendar_id)
69
+ Calendar.new(:client_id => 'abadid', :client_secret => 'abadsecret', :redirect_url => @redirect_url,
70
+ :refresh_token => @refresh_token, :calendar => @calendar_id)
48
71
  end
49
72
  end
50
73
 
@@ -63,13 +86,31 @@ class TestGoogleCalendar < Minitest::Test
63
86
 
64
87
  calendar = Calendar.new({:calendar => @calendar_id}, reusable_connection)
65
88
  calendar.events
66
- end
89
+ end
90
+
91
+ should "throw ForbiddenError if not logged in" do
92
+ @client_mock.stubs(:status).returns(403)
93
+ @client_mock.stubs(:body).returns( get_mock_body("403_forbidden.json") )
94
+
95
+ assert_raises(ForbiddenError) do
96
+ @calendar.find_event_by_id('1234')
97
+ end
98
+ end
99
+
100
+ should "throw ForbiddenError if unknown 403 response" do
101
+ @client_mock.stubs(:status).returns(403)
102
+ @client_mock.stubs(:body).returns( get_mock_body("403_unknown.json") )
103
+
104
+ assert_raises(ForbiddenError) do
105
+ @calendar.find_event_by_id('1234')
106
+ end
107
+ end
67
108
 
68
109
  end # login context
69
110
 
70
111
  context "and logged in" do
71
112
  setup do
72
- @calendar = Calendar.new(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => "urn:ietf:wg:oauth:2.0:oob", :refresh_token => @refresh_token, :calendar => @calendar_id)
113
+ @calendar = Calendar.new(:client_id => @client_id, :client_secret => @client_secret, :redirect_url => @redirect_url, :refresh_token => @refresh_token, :calendar => @calendar_id)
73
114
  end
74
115
 
75
116
  should "find all events" do
@@ -159,6 +200,96 @@ class TestGoogleCalendar < Minitest::Test
159
200
  assert_equal @calendar.find_event_by_id('1234'), []
160
201
  end
161
202
 
203
+ should "throw Request Failed with 400 error" do
204
+ @client_mock.stubs(:status).returns(400)
205
+ @client_mock.stubs(:body).returns( get_mock_body("400.json") )
206
+
207
+ assert_raises(HTTPRequestFailed) do
208
+ @calendar.create_event do |e|
209
+ e.title = 'New Event with no time'
210
+ e.description = "A new event with &"
211
+ e.location = "Joe's House & Backyard"
212
+ end
213
+ end
214
+ end
215
+
216
+ should "throw DailyLimitExceededError when limit exceeded" do
217
+ @client_mock.stubs(:status).returns(403)
218
+ @client_mock.stubs(:body).returns( get_mock_body("403_daily_limit.json") )
219
+
220
+ assert_raises(DailyLimitExceededError) do
221
+ @calendar.find_event_by_id('1234')
222
+ end
223
+ end
224
+
225
+ should "throw RateLimitExceededError when rate limit exceeded" do
226
+ @client_mock.stubs(:status).returns(403)
227
+ @client_mock.stubs(:body).returns( get_mock_body("403_rate_limit.json") )
228
+
229
+ assert_raises(RateLimitExceededError) do
230
+ @calendar.find_event_by_id('1234')
231
+ end
232
+ end
233
+
234
+ should "throw UserRateLimitExceededError when user rate limit exceeded" do
235
+ @client_mock.stubs(:status).returns(403)
236
+ @client_mock.stubs(:body).returns( get_mock_body("403_user_rate_limit.json") )
237
+
238
+ assert_raises(UserRateLimitExceededError) do
239
+ @calendar.find_event_by_id('1234')
240
+ end
241
+ end
242
+
243
+ should "throw CalendarUsageLimitExceededError when calendar rate limit exceeded" do
244
+ @client_mock.stubs(:status).returns(403)
245
+ @client_mock.stubs(:body).returns( get_mock_body("403_calendar_rate_limit.json") )
246
+
247
+ assert_raises(CalendarUsageLimitExceededError) do
248
+ @calendar.find_event_by_id('1234')
249
+ end
250
+ end
251
+
252
+ should "throw RequestedIdentifierAlreadyExistsError if bad eTag" do
253
+ @client_mock.stubs(:status).returns(409)
254
+ @client_mock.stubs(:body).returns( get_mock_body("409.json") )
255
+
256
+ assert_raises(RequestedIdentifierAlreadyExistsError) do
257
+ @calendar.create_event do |e|
258
+ e.id = 'duplicate'
259
+ e.title = 'New Event'
260
+ e.start_time = Time.now + (60 * 60)
261
+ e.end_time = Time.now + (60 * 60 * 2)
262
+ end
263
+ end
264
+ end
265
+
266
+ should "throw GoneError if bad eTag" do
267
+ @client_mock.stubs(:status).returns(410)
268
+ @client_mock.stubs(:body).returns( get_mock_body("410.json") )
269
+
270
+ assert_raises(GoneError) do
271
+ @calendar.find_event_by_id('deleted')
272
+ end
273
+ end
274
+
275
+ should "throw PreconditionFailedError if bad eTag" do
276
+ @client_mock.stubs(:status).returns(412)
277
+ @client_mock.stubs(:body).returns( get_mock_body("412.json") )
278
+
279
+ assert_raises(PreconditionFailedError) do
280
+ @calendar.find_event_by_id('1234')
281
+ end
282
+ end
283
+
284
+ should "throw BackendError if Google is having issues" do
285
+ @client_mock.stubs(:status).returns(500)
286
+ @client_mock.stubs(:body).returns( get_mock_body("500.json") )
287
+
288
+ assert_raises(BackendError) do
289
+ @calendar.find_event_by_id('1234')
290
+ end
291
+ end
292
+
162
293
  should "create an event with block" do
163
294
  @client_mock.stubs(:body).returns( get_mock_body("create_event.json") )
164
295
 
@@ -248,7 +379,7 @@ class TestGoogleCalendar < Minitest::Test
248
379
 
249
380
  @client_mock.stubs(:body).returns('')
250
381
  event.delete
251
- assert_equal event.id, nil
382
+ assert_nil event.id
252
383
  end
253
384
 
254
385
  should "throw exception on bad request" do
@@ -258,14 +389,14 @@ class TestGoogleCalendar < Minitest::Test
258
389
  end
259
390
  end
260
391
 
261
- should "create event when id is NIL" do
392
+ should "create event when id is nil" do
262
393
  @client_mock.stubs(:body).returns( get_mock_body("find_event_by_id.json") )
263
394
 
264
- event = @calendar.find_or_create_event_by_id(NIL) do |e|
265
- e.title = 'New Event Update when id is NIL'
395
+ event = @calendar.find_or_create_event_by_id(nil) do |e|
396
+ e.title = 'New Event Update when id is nil'
266
397
  end
267
398
 
268
- assert_equal event.title, 'New Event Update when id is NIL'
399
+ assert_equal event.title, 'New Event Update when id is nil'
269
400
  end
270
401
 
271
402
  should "provide the calendar summary" do
@@ -285,10 +416,10 @@ class TestGoogleCalendar < Minitest::Test
285
416
  event.id = '8os94knodtv84h0jh4pqq4ut35'
286
417
  assert_equal event.id, '8os94knodtv84h0jh4pqq4ut35'
287
418
  end
288
- should "work with a passed-in NIL id" do
419
+ should "work with a passed-in nil id" do
289
420
  event = Event.new
290
421
  event.id = nil
291
- assert_equal event.id, nil
422
+ assert_nil event.id
292
423
  end
293
424
  should "raise an error with an invalid ID" do
294
425
  event = Event.new
@@ -519,11 +650,12 @@ class TestGoogleCalendar < Minitest::Test
519
650
  @client_id = "671053090364-ntifn8rauvhib9h3vnsegi6dhfglk9ue.apps.googleusercontent.com"
520
651
  @client_secret = "roBgdbfEmJwPgrgi2mRbbO-f"
521
652
  @refresh_token = "1/eiqBWx8aj-BsdhwvlzDMFOUN1IN_HyThvYTujyksO4c"
653
+ @redirect_url = "urn:ietf:wg:oauth:2.0:oob"
522
654
 
523
655
  @calendar_list = Google::CalendarList.new(
524
656
  :client_id => @client_id,
525
657
  :client_secret => @client_secret,
526
- :redirect_url => "urn:ietf:wg:oauth:2.0:oob",
658
+ :redirect_url => @redirect_url,
527
659
  :refresh_token => @refresh_token
528
660
  )
529
661
 
@@ -573,11 +705,12 @@ class TestGoogleCalendar < Minitest::Test
573
705
  @client_id = "671053090364-ntifn8rauvhib9h3vnsegi6dhfglk9ue.apps.googleusercontent.com"
574
706
  @client_secret = "roBgdbfEmJwPgrgi2mRbbO-f"
575
707
  @refresh_token = "1/eiqBWx8aj-BsdhwvlzDMFOUN1IN_HyThvYTujyksO4c"
708
+ @redirect_url = "urn:ietf:wg:oauth:2.0:oob"
576
709
 
577
710
  @freebusy = Google::Freebusy.new(
578
711
  :client_id => @client_id,
579
712
  :client_secret => @client_secret,
580
- :redirect_url => "urn:ietf:wg:oauth:2.0:oob",
713
+ :redirect_url => @redirect_url,
581
714
  :refresh_token => @refresh_token
582
715
  )
583
716
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_calendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Zich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-17 00:00:00.000000000 Z
11
+ date: 2018-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: signet
@@ -31,9 +31,6 @@ dependencies:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.8.3
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '2.1'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
@@ -41,23 +38,20 @@ dependencies:
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
40
  version: 1.8.3
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '2.1'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: TimezoneParser
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
45
  - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: 0.2.0
47
+ version: 0.3.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
51
  requirements:
58
52
  - - "~>"
59
53
  - !ruby/object:Gem::Version
60
- version: 0.2.0
54
+ version: 0.3.0
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: terminal-notifier-guard
63
57
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +100,14 @@ dependencies:
106
100
  requirements:
107
101
  - - "~>"
108
102
  - !ruby/object:Gem::Version
109
- version: '1.0'
103
+ version: '1.2'
110
104
  type: :development
111
105
  prerelease: false
112
106
  version_requirements: !ruby/object:Gem::Requirement
113
107
  requirements:
114
108
  - - "~>"
115
109
  - !ruby/object:Gem::Version
116
- version: '1.0'
110
+ version: '1.2'
117
111
  - !ruby/object:Gem::Dependency
118
112
  name: shoulda-context
119
113
  requirement: !ruby/object:Gem::Requirement
@@ -148,40 +142,40 @@ dependencies:
148
142
  requirements:
149
143
  - - "~>"
150
144
  - !ruby/object:Gem::Version
151
- version: '1.1'
145
+ version: '1.4'
152
146
  type: :development
153
147
  prerelease: false
154
148
  version_requirements: !ruby/object:Gem::Requirement
155
149
  requirements:
156
150
  - - "~>"
157
151
  - !ruby/object:Gem::Version
158
- version: '1.1'
152
+ version: '1.4'
159
153
  - !ruby/object:Gem::Dependency
160
154
  name: rake
161
155
  requirement: !ruby/object:Gem::Requirement
162
156
  requirements:
163
- - - "~>"
157
+ - - ">="
164
158
  - !ruby/object:Gem::Version
165
159
  version: '11'
166
160
  type: :development
167
161
  prerelease: false
168
162
  version_requirements: !ruby/object:Gem::Requirement
169
163
  requirements:
170
- - - "~>"
164
+ - - ">="
171
165
  - !ruby/object:Gem::Version
172
166
  version: '11'
173
167
  - !ruby/object:Gem::Dependency
174
168
  name: rdoc
175
169
  requirement: !ruby/object:Gem::Requirement
176
170
  requirements:
177
- - - "~>"
171
+ - - ">="
178
172
  - !ruby/object:Gem::Version
179
173
  version: '4.1'
180
174
  type: :development
181
175
  prerelease: false
182
176
  version_requirements: !ruby/object:Gem::Requirement
183
177
  requirements:
184
- - - "~>"
178
+ - - ">="
185
179
  - !ruby/object:Gem::Version
186
180
  version: '4.1'
187
181
  - !ruby/object:Gem::Dependency
@@ -229,10 +223,22 @@ files:
229
223
  - lib/google_calendar.rb
230
224
  - readme_code.rb
231
225
  - test/helper.rb
226
+ - test/mocks/400.json
232
227
  - test/mocks/401.json
233
228
  - test/mocks/403.json
229
+ - test/mocks/403_calendar_rate_limit.json
230
+ - test/mocks/403_daily_limit.json
231
+ - test/mocks/403_forbidden.json
232
+ - test/mocks/403_rate_limit.json
233
+ - test/mocks/403_unknown.json
234
+ - test/mocks/403_user_rate_limit.json
234
235
  - test/mocks/404.json
236
+ - test/mocks/409.json
237
+ - test/mocks/410.json
238
+ - test/mocks/412.json
239
+ - test/mocks/500.json
235
240
  - test/mocks/cancelled_events.json
241
+ - test/mocks/create_calendar.json
236
242
  - test/mocks/create_event.json
237
243
  - test/mocks/create_quickadd_event.json
238
244
  - test/mocks/empty_events.json
@@ -241,6 +247,7 @@ files:
241
247
  - test/mocks/find_calendar_list.json
242
248
  - test/mocks/find_event_by_id.json
243
249
  - test/mocks/freebusy_query.json
250
+ - test/mocks/get_calendar.json
244
251
  - test/mocks/login_with_auth_code_fail.json
245
252
  - test/mocks/login_with_auth_code_success.json
246
253
  - test/mocks/login_with_refresh_token_success.json
@@ -248,6 +255,7 @@ files:
248
255
  - test/mocks/query_events.json
249
256
  - test/mocks/repeating_events.json
250
257
  - test/mocks/successful_login.json
258
+ - test/mocks/update_calendar.json
251
259
  - test/test_google_calendar.rb
252
260
  homepage: http://northworld.github.io/google_calendar/
253
261
  licenses:
@@ -269,16 +277,28 @@ required_rubygems_version: !ruby/object:Gem::Requirement
269
277
  version: '0'
270
278
  requirements: []
271
279
  rubyforge_project:
272
- rubygems_version: 2.6.10
280
+ rubygems_version: 2.6.14
273
281
  signing_key:
274
282
  specification_version: 4
275
283
  summary: A lightweight Google Calendar API wrapper
276
284
  test_files:
277
285
  - test/helper.rb
286
+ - test/mocks/400.json
278
287
  - test/mocks/401.json
279
288
  - test/mocks/403.json
289
+ - test/mocks/403_calendar_rate_limit.json
290
+ - test/mocks/403_daily_limit.json
291
+ - test/mocks/403_forbidden.json
292
+ - test/mocks/403_rate_limit.json
293
+ - test/mocks/403_unknown.json
294
+ - test/mocks/403_user_rate_limit.json
280
295
  - test/mocks/404.json
296
+ - test/mocks/409.json
297
+ - test/mocks/410.json
298
+ - test/mocks/412.json
299
+ - test/mocks/500.json
281
300
  - test/mocks/cancelled_events.json
301
+ - test/mocks/create_calendar.json
282
302
  - test/mocks/create_event.json
283
303
  - test/mocks/create_quickadd_event.json
284
304
  - test/mocks/empty_events.json
@@ -287,6 +307,7 @@ test_files:
287
307
  - test/mocks/find_calendar_list.json
288
308
  - test/mocks/find_event_by_id.json
289
309
  - test/mocks/freebusy_query.json
310
+ - test/mocks/get_calendar.json
290
311
  - test/mocks/login_with_auth_code_fail.json
291
312
  - test/mocks/login_with_auth_code_success.json
292
313
  - test/mocks/login_with_refresh_token_success.json
@@ -294,4 +315,5 @@ test_files:
294
315
  - test/mocks/query_events.json
295
316
  - test/mocks/repeating_events.json
296
317
  - test/mocks/successful_login.json
318
+ - test/mocks/update_calendar.json
297
319
  - test/test_google_calendar.rb