calendlyr 0.7.4 → 0.10.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +9 -5
- data/.gitignore +2 -1
- data/CHANGELOG.md +66 -0
- data/README.md +31 -79
- data/calendlyr.gemspec +6 -7
- data/docs/resources/data_compliance.md +1 -1
- data/docs/resources/event_types/availability_schedule.md +28 -0
- data/docs/resources/event_types/event_type.md +18 -7
- data/docs/resources/events/cancellation.md +1 -1
- data/docs/resources/events/event.md +2 -2
- data/docs/resources/events/invitee.md +17 -0
- data/docs/resources/locations/location.md +16 -0
- data/docs/resources/organizations/organization.md +0 -9
- data/docs/resources/share.md +2 -9
- data/docs/resources/webhooks/invitee_payload.md +1 -1
- data/docs/resources/webhooks/payload.md +1 -1
- data/docs/resources/webhooks/subscription.md +1 -1
- data/lib/calendlyr/client.rb +20 -45
- data/lib/calendlyr/collection.rb +18 -3
- data/lib/calendlyr/error.rb +17 -26
- data/lib/calendlyr/object.rb +77 -14
- data/lib/calendlyr/objects/event_type.rb +0 -4
- data/lib/calendlyr/objects/event_types/availability_schedule.rb +8 -0
- data/lib/calendlyr/objects/events/invitee.rb +1 -1
- data/lib/calendlyr/objects/location.rb +4 -0
- data/lib/calendlyr/objects/organization.rb +0 -4
- data/lib/calendlyr/objects/share.rb +0 -5
- data/lib/calendlyr/resource.rb +34 -7
- data/lib/calendlyr/resources/event_types.rb +37 -0
- data/lib/calendlyr/resources/{event.rb → events.rb} +6 -1
- data/lib/calendlyr/resources/{group.rb → groups.rb} +1 -1
- data/lib/calendlyr/resources/locations.rb +8 -0
- data/lib/calendlyr/resources/{organization.rb → organizations.rb} +1 -1
- data/lib/calendlyr/resources/{routing_form.rb → routing_forms.rb} +1 -1
- data/lib/calendlyr/resources/{share.rb → shares.rb} +1 -1
- data/lib/calendlyr/resources/{user.rb → users.rb} +1 -1
- data/lib/calendlyr/resources/{webhook.rb → webhooks.rb} +1 -5
- data/lib/calendlyr/version.rb +1 -1
- data/lib/calendlyr.rb +15 -15
- data/test/calendlyr/client_test.rb +25 -0
- data/test/calendlyr/collection_test.rb +64 -0
- data/test/calendlyr/object_test.rb +32 -1
- data/test/calendlyr/objects/event_type_test.rb +0 -15
- data/test/calendlyr/objects/event_types/availability_schedule_test.rb +20 -0
- data/test/calendlyr/objects/events/cancellation_test.rb +1 -1
- data/test/calendlyr/objects/events/guest_test.rb +1 -1
- data/test/calendlyr/objects/events/invitee_no_show_test.rb +1 -1
- data/test/calendlyr/objects/events/invitee_test.rb +10 -3
- data/test/calendlyr/objects/location_test.rb +22 -0
- data/test/calendlyr/objects/organization_test.rb +0 -8
- data/test/calendlyr/objects/organizations/invitation_test.rb +1 -1
- data/test/calendlyr/objects/share_test.rb +3 -9
- data/test/calendlyr/resource_test.rb +178 -2
- data/test/calendlyr/resources/data_compliance_test.rb +1 -4
- data/test/calendlyr/resources/event_types_test.rb +48 -0
- data/test/calendlyr/resources/events_test.rb +19 -0
- data/test/calendlyr/resources/locations_test.rb +18 -0
- data/test/calendlyr/resources/webhooks_test.rb +0 -8
- data/test/fixtures/event_invitees/retrieve.json +11 -1
- data/test/fixtures/event_type_availability_schedules/list.json +17 -0
- data/test/fixtures/event_type_availability_schedules/update.json +3 -0
- data/test/fixtures/event_types/create.json +30 -0
- data/test/fixtures/event_types/update.json +30 -0
- data/test/fixtures/events/create_invitee.json +37 -0
- data/test/fixtures/events/retrieve.json +12 -2
- data/test/fixtures/locations/list.json +16 -0
- data/test/fixtures/objects/event.json +10 -2
- data/test/fixtures/objects/event_types/availability_schedule.json +6 -0
- data/test/fixtures/objects/location.json +5 -0
- data/test/test_helper.rb +9 -7
- metadata +47 -65
- data/docs/resources/event_types/available_time.md +0 -21
- data/docs/resources/event_types/membership.md +0 -29
- data/docs/resources/scheduling_link.md +0 -26
- data/lib/calendlyr/objects/event_types/available_time.rb +0 -4
- data/lib/calendlyr/objects/event_types/membership.rb +0 -11
- data/lib/calendlyr/objects/scheduling_link.rb +0 -9
- data/lib/calendlyr/resources/event_type.rb +0 -28
- data/lib/calendlyr/resources/outgoing_communication.rb +0 -8
- data/lib/calendlyr/resources/scheduling_link.rb +0 -8
- data/test/calendlyr/objects/event_types/available_time_test.rb +0 -20
- data/test/calendlyr/objects/event_types/membership_test.rb +0 -32
- data/test/calendlyr/objects/scheduling_link_test.rb +0 -17
- data/test/calendlyr/resources/event_types/membership_test.rb +0 -22
- data/test/calendlyr/resources/outgoing_communications_test.rb +0 -16
- data/test/calendlyr/resources/scheduling_links_test.rb +0 -15
- data/test/fixtures/event_type_available_times/list.json +0 -22
- data/test/fixtures/objects/event_types/available_time.json +0 -6
- data/test/fixtures/objects/event_types/membership.json +0 -65
- data/test/fixtures/objects/scheduling_links/event_type.json +0 -5
- data/test/fixtures/outgoing_communications/list.json +0 -26
- data/test/fixtures/scheduling_links/create.json +0 -7
- data/test/fixtures/webhooks/sample.json +0 -105
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
module EventTypes
|
|
6
|
+
class AvailabilityScheduleObjectTest < Minitest::Test
|
|
7
|
+
def setup
|
|
8
|
+
json = JSON.parse(fixture_file("objects/event_types/availability_schedule")).merge(client: client)
|
|
9
|
+
@availability_schedule = Calendlyr::EventTypes::AvailabilitySchedule.new(json)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_uri
|
|
13
|
+
assert_equal "https://api.calendly.com/event_type_availability_schedules/AAAAAAAAAAAAAAAA", @availability_schedule.uri
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_event_type
|
|
17
|
+
assert_equal "https://api.calendly.com/event_types/BBBBBBBBBBBBBBBB", @availability_schedule.event_type
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -10,14 +10,21 @@ module Events
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def test_email
|
|
13
|
-
|
|
13
|
+
assert_equal "test@example.com", @invitee.email
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def test_cancel
|
|
17
|
+
invitee = Calendlyr::Events::Invitee.new(
|
|
18
|
+
JSON.parse(fixture_file("objects/events/invitee")).merge(
|
|
19
|
+
"event" => "https://api.calendly.com/scheduled_events/EVT123",
|
|
20
|
+
"uri" => "https://api.calendly.com/scheduled_events/EVT123/invitees/INV456",
|
|
21
|
+
:client => client
|
|
22
|
+
)
|
|
23
|
+
)
|
|
17
24
|
response = {body: fixture_file("events/cancel_invitee"), status: 201}
|
|
18
|
-
stub(method: :post, path: "scheduled_events
|
|
25
|
+
stub(method: :post, path: "scheduled_events/EVT123/cancellation", response: response)
|
|
19
26
|
|
|
20
|
-
cancellation =
|
|
27
|
+
cancellation = invitee.cancel(reason: "I'm busy")
|
|
21
28
|
|
|
22
29
|
assert_instance_of Calendlyr::Events::Cancellation, cancellation
|
|
23
30
|
assert_equal "host", cancellation.canceler_type
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class LocationObjectTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
json = JSON.parse(fixture_file("objects/location")).merge(client: client)
|
|
8
|
+
@location = Calendlyr::Location.new(json)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_uri
|
|
12
|
+
assert_equal "https://api.calendly.com/locations/AAAAAAAAAAAAAAAA", @location.uri
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_type
|
|
16
|
+
assert_equal "zoom", @location.type
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_display_name
|
|
20
|
+
assert_equal "Zoom", @location.display_name
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -111,14 +111,6 @@ class OrganizatonObjectTest < Minitest::Test
|
|
|
111
111
|
assert @organization.create_webhook(**body)
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
def test_sample_webhook_data
|
|
115
|
-
stub(path: "sample_webhook_data?event=invitee.created&scope=organization&organization=https://api.calendly.com/organizations/012345678901234567890", response: {body: fixture_file("webhooks/sample"), status: 200})
|
|
116
|
-
webhook_data = @organization.sample_webhook_data(event: "invitee.created", scope: "organization")
|
|
117
|
-
|
|
118
|
-
assert_instance_of Calendlyr::Object, webhook_data
|
|
119
|
-
assert_equal "invitee.created", webhook_data.event
|
|
120
|
-
end
|
|
121
|
-
|
|
122
114
|
def test_invite_user
|
|
123
115
|
email = "email@example.com"
|
|
124
116
|
response = {body: fixture_file("organizations/invite"), status: 201}
|
|
@@ -12,7 +12,7 @@ module Organizations
|
|
|
12
12
|
stub(method: :delete, path: "organizations/#{@invitation.associated_organization.uuid}/invitations/#{@invitation.uuid}", response: response)
|
|
13
13
|
|
|
14
14
|
response = {body: fixture_file("users/retrieve"), status: 200}
|
|
15
|
-
stub(path: "users/#{
|
|
15
|
+
stub(path: "users/#{@invitation.user.split("/").last}", response: response)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def test_associated_organization
|
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class ShareObjectTest < Minitest::Test
|
|
6
|
-
def
|
|
6
|
+
def test_share
|
|
7
7
|
json = JSON.parse(fixture_file("objects/share")).merge(client: client)
|
|
8
8
|
@share = Calendlyr::Share.new(json)
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
scheculing_links = @share.associated_scheduling_links
|
|
14
|
-
|
|
15
|
-
assert_equal 1, scheculing_links.size
|
|
16
|
-
assert_equal Calendlyr::SchedulingLink, scheculing_links.first.class
|
|
17
|
-
assert_equal Calendlyr::EventType, scheculing_links.first.event_type.class
|
|
10
|
+
assert_instance_of Calendlyr::Share, @share
|
|
11
|
+
assert_equal 1, @share.scheduling_links.size
|
|
18
12
|
end
|
|
19
13
|
end
|
|
@@ -3,11 +3,43 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class ResourceTest < Minitest::Test
|
|
6
|
+
class HttpSpy
|
|
7
|
+
attr_reader :host, :port, :last_request, :request_count
|
|
8
|
+
attr_accessor :use_ssl, :open_timeout, :read_timeout
|
|
9
|
+
|
|
10
|
+
def initialize(responses:, host:, port:)
|
|
11
|
+
@responses = responses
|
|
12
|
+
@host = host
|
|
13
|
+
@port = port
|
|
14
|
+
@request_count = 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def request(request)
|
|
18
|
+
@last_request = request
|
|
19
|
+
@request_count += 1
|
|
20
|
+
@responses.fetch(@request_count - 1)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class ResponseStub
|
|
25
|
+
attr_reader :body, :code
|
|
26
|
+
|
|
27
|
+
def initialize(body:, code:, headers: {})
|
|
28
|
+
@body = body
|
|
29
|
+
@code = code
|
|
30
|
+
@headers = headers
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def [](header)
|
|
34
|
+
@headers[header]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
6
38
|
def test_handle_response_error
|
|
7
|
-
Calendlyr::
|
|
39
|
+
Calendlyr::ERROR_TYPES.each do |error_code, error_class|
|
|
8
40
|
stub(path: "users/me", response: {body: fixture_file("resources/#{error_code}"), status: error_code.to_i})
|
|
9
41
|
|
|
10
|
-
assert_raises
|
|
42
|
+
assert_raises Calendlyr.const_get(error_class) do
|
|
11
43
|
client.me
|
|
12
44
|
end
|
|
13
45
|
end
|
|
@@ -20,4 +52,148 @@ class ResourceTest < Minitest::Test
|
|
|
20
52
|
client.me
|
|
21
53
|
end
|
|
22
54
|
end
|
|
55
|
+
|
|
56
|
+
def test_handle_response_too_many_requests
|
|
57
|
+
stub(path: "users/me", response: {body: "", status: 429})
|
|
58
|
+
|
|
59
|
+
assert_raises Calendlyr::TooManyRequests do
|
|
60
|
+
client.me
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_handle_response_invalid_json_returns_empty_hash
|
|
65
|
+
resource = Calendlyr::Resource.new(client)
|
|
66
|
+
response = ResponseStub.new(body: "not json", code: "200")
|
|
67
|
+
|
|
68
|
+
assert_equal({}, resource.send(:handle_response, response))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_handle_response_non_json_errors_propagate
|
|
72
|
+
resource = Calendlyr::Resource.new(client)
|
|
73
|
+
response = ResponseStub.new(body: '{"key":"value"}', code: "200")
|
|
74
|
+
|
|
75
|
+
JSON.stub(:parse, proc { raise StandardError, "boom" }) do
|
|
76
|
+
assert_raises StandardError do
|
|
77
|
+
resource.send(:handle_response, response)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_request_uses_default_client_timeouts
|
|
83
|
+
resource = Calendlyr::Resource.new(client)
|
|
84
|
+
response = ResponseStub.new(body: "{}", code: "200")
|
|
85
|
+
http_spy = HttpSpy.new(responses: [response], host: "api.calendly.com", port: 443)
|
|
86
|
+
|
|
87
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
88
|
+
resource.send(:request, "users/me", Net::HTTP::Get)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
assert_equal 30, http_spy.open_timeout
|
|
92
|
+
assert_equal 30, http_spy.read_timeout
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_request_uses_custom_client_timeouts
|
|
96
|
+
custom_client = Calendlyr::Client.new(token: "fake", open_timeout: 10, read_timeout: 12)
|
|
97
|
+
resource = Calendlyr::Resource.new(custom_client)
|
|
98
|
+
response = ResponseStub.new(body: "{}", code: "200")
|
|
99
|
+
http_spy = HttpSpy.new(responses: [response], host: "api.calendly.com", port: 443)
|
|
100
|
+
|
|
101
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
102
|
+
resource.send(:request, "users/me", Net::HTTP::Get)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
assert_equal 10, http_spy.open_timeout
|
|
106
|
+
assert_equal 12, http_spy.read_timeout
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_request_retries_after_429_and_returns_success_response
|
|
110
|
+
resource = Calendlyr::Resource.new(client)
|
|
111
|
+
responses = [
|
|
112
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429"),
|
|
113
|
+
ResponseStub.new(body: '{"ok":true}', code: "200")
|
|
114
|
+
]
|
|
115
|
+
http_spy = HttpSpy.new(responses: responses, host: "api.calendly.com", port: 443)
|
|
116
|
+
sleeps = []
|
|
117
|
+
|
|
118
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
119
|
+
resource.stub(:sleep, proc { |seconds| sleeps << seconds }) do
|
|
120
|
+
result = resource.send(:get_request, "users/me")
|
|
121
|
+
|
|
122
|
+
assert_equal({"ok" => true}, result)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
assert_equal 2, http_spy.request_count
|
|
127
|
+
assert_equal [1], sleeps
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_request_uses_retry_after_header_on_429
|
|
131
|
+
resource = Calendlyr::Resource.new(client)
|
|
132
|
+
responses = [
|
|
133
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429", headers: {"Retry-After" => "5"}),
|
|
134
|
+
ResponseStub.new(body: '{"ok":true}', code: "200")
|
|
135
|
+
]
|
|
136
|
+
http_spy = HttpSpy.new(responses: responses, host: "api.calendly.com", port: 443)
|
|
137
|
+
sleeps = []
|
|
138
|
+
|
|
139
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
140
|
+
resource.stub(:sleep, proc { |seconds| sleeps << seconds }) do
|
|
141
|
+
resource.send(:get_request, "users/me")
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
assert_equal [5], sleeps
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_request_raises_too_many_requests_after_exhausting_retries
|
|
149
|
+
resource = Calendlyr::Resource.new(client)
|
|
150
|
+
responses = [
|
|
151
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429"),
|
|
152
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429"),
|
|
153
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429"),
|
|
154
|
+
ResponseStub.new(body: fixture_file("resources/429"), code: "429")
|
|
155
|
+
]
|
|
156
|
+
http_spy = HttpSpy.new(responses: responses, host: "api.calendly.com", port: 443)
|
|
157
|
+
sleeps = []
|
|
158
|
+
|
|
159
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
160
|
+
resource.stub(:sleep, proc { |seconds| sleeps << seconds }) do
|
|
161
|
+
assert_raises Calendlyr::TooManyRequests do
|
|
162
|
+
resource.send(:get_request, "users/me")
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
assert_equal [1, 2, 4], sleeps
|
|
168
|
+
assert_equal 4, http_spy.request_count
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_request_does_not_retry_non_429_errors
|
|
172
|
+
resource = Calendlyr::Resource.new(client)
|
|
173
|
+
responses = [ResponseStub.new(body: fixture_file("resources/401"), code: "401")]
|
|
174
|
+
http_spy = HttpSpy.new(responses: responses, host: "api.calendly.com", port: 443)
|
|
175
|
+
|
|
176
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
177
|
+
resource.stub(:sleep, proc { raise "sleep should not be called" }) do
|
|
178
|
+
assert_raises Calendlyr::Unauthenticated do
|
|
179
|
+
resource.send(:get_request, "users/me")
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
assert_equal 1, http_spy.request_count
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def test_put_request_sends_json_body_and_handles_response
|
|
188
|
+
resource = Calendlyr::Resource.new(client)
|
|
189
|
+
response = ResponseStub.new(body: '{"updated":true}', code: "200")
|
|
190
|
+
http_spy = HttpSpy.new(responses: [response], host: "api.calendly.com", port: 443)
|
|
191
|
+
|
|
192
|
+
Net::HTTP.stub(:new, http_spy) do
|
|
193
|
+
result = resource.send(:put_request, "users/me", body: {key: "val"})
|
|
194
|
+
|
|
195
|
+
assert_equal({"updated" => true}, result)
|
|
196
|
+
assert_equal "{\"key\":\"val\"}", http_spy.last_request.body
|
|
197
|
+
end
|
|
198
|
+
end
|
|
23
199
|
end
|
|
@@ -12,10 +12,7 @@ class DataComplianceResourceTest < Minitest::Test
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def test_delete_scheduled_event_data
|
|
15
|
-
body = {
|
|
16
|
-
start_time: "2019-01-02T03:04:05.678123Z",
|
|
17
|
-
end_time: "2021-01-01T02:04:05.678123Z"
|
|
18
|
-
}
|
|
15
|
+
body = {start_time: "2019-01-02T03:04:05.678123Z", end_time: "2021-01-01T02:04:05.678123Z"}
|
|
19
16
|
response = {body: fixture_file("data_compliance/delete_scheduled_event_data"), status: 202}
|
|
20
17
|
stub(method: :post, path: "data_compliance/deletion/events", body: body, response: response)
|
|
21
18
|
|
|
@@ -73,4 +73,52 @@ class EventTypesResourceTest < Minitest::Test
|
|
|
73
73
|
assert_equal "acmesales", event_type.slug
|
|
74
74
|
assert_equal 30, event_type.duration
|
|
75
75
|
end
|
|
76
|
+
|
|
77
|
+
def test_create
|
|
78
|
+
body = {
|
|
79
|
+
name: "30 Minute Meeting",
|
|
80
|
+
duration: 30,
|
|
81
|
+
pooling_type: "round_robin"
|
|
82
|
+
}
|
|
83
|
+
stub(method: :post, path: "event_types", response: {body: fixture_file("event_types/create"), status: 201})
|
|
84
|
+
event_type = client.event_types.create(**body)
|
|
85
|
+
|
|
86
|
+
assert_equal Calendlyr::EventType, event_type.class
|
|
87
|
+
assert_equal "https://api.calendly.com/event_types/AAAAAAAAAAAAAAAA", event_type.uri
|
|
88
|
+
assert_equal "30 Minute Meeting", event_type.name
|
|
89
|
+
assert_equal 30, event_type.duration
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_update
|
|
93
|
+
stub(method: :patch, path: "event_types/#{@event_type_uuid}", response: {body: fixture_file("event_types/update"), status: 200})
|
|
94
|
+
event_type = client.event_types.update(uuid: @event_type_uuid, name: "Updated Meeting", duration: 45)
|
|
95
|
+
|
|
96
|
+
assert_equal Calendlyr::EventType, event_type.class
|
|
97
|
+
assert_equal "https://api.calendly.com/event_types/AAAAAAAAAAAAAAAA", event_type.uri
|
|
98
|
+
assert_equal "Updated Meeting", event_type.name
|
|
99
|
+
assert_equal 45, event_type.duration
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_list_availability_schedules
|
|
103
|
+
stub(path: "event_type_availability_schedules?event_type_uuid=AAAAAAAAAAAAAAAA", response: {body: fixture_file("event_type_availability_schedules/list"), status: 200})
|
|
104
|
+
schedules = client.event_types.list_availability_schedules(event_type_uuid: "AAAAAAAAAAAAAAAA")
|
|
105
|
+
|
|
106
|
+
assert_equal Calendlyr::Collection, schedules.class
|
|
107
|
+
assert_equal Calendlyr::EventTypes::AvailabilitySchedule, schedules.data.first.class
|
|
108
|
+
assert_equal 1, schedules.data.count
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_update_availability_schedule
|
|
112
|
+
body = {
|
|
113
|
+
event_type_uuid: "AAAAAAAAAAAAAAAA",
|
|
114
|
+
availability_schedules: [
|
|
115
|
+
{start_time: "2023-10-27T09:00:00Z", end_time: "2023-10-27T12:00:00Z"}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
stub(method: :patch, path: "event_type_availability_schedules", response: {body: fixture_file("event_type_availability_schedules/update"), status: 200})
|
|
119
|
+
result = client.event_types.update_availability_schedule(**body)
|
|
120
|
+
|
|
121
|
+
assert result
|
|
122
|
+
assert_equal "Availability schedules updated successfully.", result["message"]
|
|
123
|
+
end
|
|
76
124
|
end
|
|
@@ -38,4 +38,23 @@ class EventsResourceTest < Minitest::Test
|
|
|
38
38
|
assert_equal "https://api.calendly.com/scheduled_events/GBGBDCAADAEDCRZ2", event.uri
|
|
39
39
|
assert_equal "15 Minute Meeting", event.name
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
def test_create_invitee
|
|
43
|
+
body = {
|
|
44
|
+
event_type: "https://api.calendly.com/event_types/AAAAAAAAAAAAAAAA",
|
|
45
|
+
start_time: "2019-08-07T06:05:04.321123Z",
|
|
46
|
+
invitee: {
|
|
47
|
+
name: "John Doe",
|
|
48
|
+
email: "test@example.com",
|
|
49
|
+
timezone: "America/New_York"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
stub(method: :post, path: "invitees", response: {body: fixture_file("events/create_invitee"), status: 201})
|
|
53
|
+
invitee = client.events.create_invitee(**body)
|
|
54
|
+
|
|
55
|
+
assert_equal Calendlyr::Events::Invitee, invitee.class
|
|
56
|
+
assert_equal "test@example.com", invitee.email
|
|
57
|
+
assert_equal "John Doe", invitee.name
|
|
58
|
+
assert_equal "active", invitee.status
|
|
59
|
+
end
|
|
41
60
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class LocationsResourceTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
list_response = {body: fixture_file("locations/list"), status: 200}
|
|
8
|
+
stub(path: "locations", response: list_response)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_list
|
|
12
|
+
locations = client.locations.list
|
|
13
|
+
|
|
14
|
+
assert_equal Calendlyr::Collection, locations.class
|
|
15
|
+
assert_equal Calendlyr::Location, locations.data.first.class
|
|
16
|
+
assert_equal 1, locations.data.count
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -43,12 +43,4 @@ class WebhooksResourceTest < Minitest::Test
|
|
|
43
43
|
stub(method: :delete, path: "webhook_subscriptions/#{webhook_uuid}", response: response)
|
|
44
44
|
assert client.webhooks.delete(webhook_uuid: webhook_uuid)
|
|
45
45
|
end
|
|
46
|
-
|
|
47
|
-
def test_sample_webhook_data
|
|
48
|
-
stub(path: "sample_webhook_data?event=invitee.created&scope=organization&organization=https://api.calendly.com/organizations/abc123", response: {body: fixture_file("webhooks/sample"), status: 200})
|
|
49
|
-
webhook_data = client.webhooks.sample_webhook_data(event: "invitee.created", scope: "organization", organization: "https://api.calendly.com/organizations/abc123")
|
|
50
|
-
|
|
51
|
-
assert_equal Calendlyr::Object, webhook_data.class
|
|
52
|
-
assert_equal "invitee.created", webhook_data.event
|
|
53
|
-
end
|
|
54
46
|
end
|
|
@@ -35,6 +35,16 @@
|
|
|
35
35
|
"currency": "USD",
|
|
36
36
|
"terms": "sample terms of payment (up to 1,024 characters)",
|
|
37
37
|
"successful": true
|
|
38
|
-
}
|
|
38
|
+
},
|
|
39
|
+
"no_show": {
|
|
40
|
+
"uri": "https://api.calendly.com/invitee_no_shows/AAAAAAAAAAAAAAAA",
|
|
41
|
+
"created_at": "2019-01-02T03:04:05.678123Z"
|
|
42
|
+
},
|
|
43
|
+
"reconfirmation": {
|
|
44
|
+
"created_at": "2020-11-23T17:51:18.341657Z",
|
|
45
|
+
"confirmed_at": "2020-11-23T17:51:18.341657Z"
|
|
46
|
+
},
|
|
47
|
+
"scheduling_method": "instant_book",
|
|
48
|
+
"invitee_scheduled_by": null
|
|
39
49
|
}
|
|
40
50
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collection": [
|
|
3
|
+
{
|
|
4
|
+
"uri": "https://api.calendly.com/event_type_availability_schedules/AAAAAAAAAAAAAAAA",
|
|
5
|
+
"start_time": "2023-10-27T09:00:00Z",
|
|
6
|
+
"end_time": "2023-10-27T17:00:00Z",
|
|
7
|
+
"event_type": "https://api.calendly.com/event_types/BBBBBBBBBBBBBBBB"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"pagination": {
|
|
11
|
+
"count": 1,
|
|
12
|
+
"next_page": "https://api.calendly.com/event_type_availability_schedules?page_token=sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi",
|
|
13
|
+
"next_page_token": "sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi",
|
|
14
|
+
"previous_page": null,
|
|
15
|
+
"previous_page_token": null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"resource": {
|
|
3
|
+
"uri": "https://api.calendly.com/event_types/AAAAAAAAAAAAAAAA",
|
|
4
|
+
"name": "30 Minute Meeting",
|
|
5
|
+
"active": true,
|
|
6
|
+
"slug": "30-minute-meeting",
|
|
7
|
+
"scheduling_url": "https://calendly.com/acmesales/30-minute-meeting",
|
|
8
|
+
"duration": 30,
|
|
9
|
+
"kind": "solo",
|
|
10
|
+
"pooling_type": "round_robin",
|
|
11
|
+
"type": "StandardEventType",
|
|
12
|
+
"color": "#fff200",
|
|
13
|
+
"created_at": "2019-01-02T03:04:05.678123Z",
|
|
14
|
+
"updated_at": "2019-08-07T06:05:04.321123Z",
|
|
15
|
+
"internal_note": null,
|
|
16
|
+
"description_plain": "30 Minute Meeting",
|
|
17
|
+
"description_html": "<p>30 Minute Meeting</p>",
|
|
18
|
+
"profile": {
|
|
19
|
+
"type": "User",
|
|
20
|
+
"name": "Tamara Jones",
|
|
21
|
+
"owner": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA"
|
|
22
|
+
},
|
|
23
|
+
"secret": false,
|
|
24
|
+
"deleted_at": null,
|
|
25
|
+
"admin_managed": false,
|
|
26
|
+
"locations": [],
|
|
27
|
+
"position": 0,
|
|
28
|
+
"custom_questions": []
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"resource": {
|
|
3
|
+
"uri": "https://api.calendly.com/event_types/AAAAAAAAAAAAAAAA",
|
|
4
|
+
"name": "Updated Meeting",
|
|
5
|
+
"active": true,
|
|
6
|
+
"slug": "updated-meeting",
|
|
7
|
+
"scheduling_url": "https://calendly.com/acmesales/updated-meeting",
|
|
8
|
+
"duration": 45,
|
|
9
|
+
"kind": "solo",
|
|
10
|
+
"pooling_type": "round_robin",
|
|
11
|
+
"type": "StandardEventType",
|
|
12
|
+
"color": "#fff200",
|
|
13
|
+
"created_at": "2019-01-02T03:04:05.678123Z",
|
|
14
|
+
"updated_at": "2019-08-07T06:05:04.321123Z",
|
|
15
|
+
"internal_note": null,
|
|
16
|
+
"description_plain": "Updated Meeting",
|
|
17
|
+
"description_html": "<p>Updated Meeting</p>",
|
|
18
|
+
"profile": {
|
|
19
|
+
"type": "User",
|
|
20
|
+
"name": "Tamara Jones",
|
|
21
|
+
"owner": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA"
|
|
22
|
+
},
|
|
23
|
+
"secret": false,
|
|
24
|
+
"deleted_at": null,
|
|
25
|
+
"admin_managed": false,
|
|
26
|
+
"locations": [],
|
|
27
|
+
"position": 0,
|
|
28
|
+
"custom_questions": []
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"resource": "https://api.calendly.com/scheduled_events/AAAAAAAAAAAAAAAA",
|
|
3
|
+
"invitee": {
|
|
4
|
+
"uri": "https://api.calendly.com/scheduled_events/AAAAAAAAAAAAAAAA/invitees/BBBBBBBBBBBBBBBB",
|
|
5
|
+
"email": "test@example.com",
|
|
6
|
+
"first_name": "John",
|
|
7
|
+
"last_name": "Doe",
|
|
8
|
+
"name": "John Doe",
|
|
9
|
+
"status": "active",
|
|
10
|
+
"questions_and_answers": [],
|
|
11
|
+
"timezone": "America/New_York",
|
|
12
|
+
"event": "https://api.calendly.com/scheduled_events/AAAAAAAAAAAAAAAA",
|
|
13
|
+
"created_at": "2019-01-02T03:04:05.678123Z",
|
|
14
|
+
"updated_at": "2019-08-07T06:05:04.321123Z",
|
|
15
|
+
"tracking": {
|
|
16
|
+
"utm_campaign": null,
|
|
17
|
+
"utm_source": null,
|
|
18
|
+
"utm_medium": null,
|
|
19
|
+
"utm_content": null,
|
|
20
|
+
"utm_term": null,
|
|
21
|
+
"salesforce_uuid": null
|
|
22
|
+
},
|
|
23
|
+
"text_reminder_number": null,
|
|
24
|
+
"rescheduled": false,
|
|
25
|
+
"old_invitee": null,
|
|
26
|
+
"new_invitee": null,
|
|
27
|
+
"cancel_url": "https://calendly.com/cancel/AAAAAAAAAAAAAAAA/BBBBBBBBBBBBBBBB",
|
|
28
|
+
"reschedule_url": "https://calendly.com/reschedule/AAAAAAAAAAAAAAAA/BBBBBBBBBBBBBBBB",
|
|
29
|
+
"routing_form_submission": null,
|
|
30
|
+
"cancellation": {},
|
|
31
|
+
"payment": null,
|
|
32
|
+
"no_show": null,
|
|
33
|
+
"reconfirmation": null,
|
|
34
|
+
"scheduling_method": "instant_book",
|
|
35
|
+
"invitee_scheduled_by": null
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
"updated_at": "2019-01-02T03:04:05.678Z",
|
|
20
20
|
"event_memberships": [
|
|
21
21
|
{
|
|
22
|
-
"user": "https://api.calendly.com/users/GBGBDCAADAEDCRZ2"
|
|
22
|
+
"user": "https://api.calendly.com/users/GBGBDCAADAEDCRZ2",
|
|
23
|
+
"buffered_start_time": "2019-08-24T14:10:00.000000Z",
|
|
24
|
+
"buffered_end_time": "2019-08-24T14:20:00.000000Z"
|
|
23
25
|
}
|
|
24
26
|
],
|
|
25
27
|
"event_guests": [
|
|
@@ -28,6 +30,14 @@
|
|
|
28
30
|
"created_at": "2019-08-24T14:15:22Z",
|
|
29
31
|
"updated_at": "2019-08-24T14:15:22Z"
|
|
30
32
|
}
|
|
31
|
-
]
|
|
33
|
+
],
|
|
34
|
+
"cancellation": {
|
|
35
|
+
"canceled_by": "host",
|
|
36
|
+
"reason": "Rescheduled",
|
|
37
|
+
"canceler_type": "host",
|
|
38
|
+
"created_at": "2019-08-24T14:15:22.123456Z"
|
|
39
|
+
},
|
|
40
|
+
"meeting_notes_plain": "Internal meeting notes",
|
|
41
|
+
"meeting_notes_html": "<p>Internal meeting notes</p>"
|
|
32
42
|
}
|
|
33
43
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collection": [
|
|
3
|
+
{
|
|
4
|
+
"uri": "https://api.calendly.com/locations/AAAAAAAAAAAAAAAA",
|
|
5
|
+
"type": "zoom",
|
|
6
|
+
"display_name": "Zoom"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"pagination": {
|
|
10
|
+
"count": 1,
|
|
11
|
+
"next_page": "https://api.calendly.com/locations?page_token=sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi",
|
|
12
|
+
"next_page_token": "sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi",
|
|
13
|
+
"previous_page": null,
|
|
14
|
+
"previous_page_token": null
|
|
15
|
+
}
|
|
16
|
+
}
|