web-ex-events 1.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +1 -0
- data/lib/web_ex/events.rb +10 -0
- data/lib/web_ex/events/configuration.rb +15 -0
- data/lib/web_ex/events/event.rb +43 -0
- data/lib/web_ex/events/event_list.rb +31 -0
- data/lib/web_ex/events/event_summary_request.rb +75 -0
- data/lib/web_ex/events/time_with_zone.rb +83 -0
- data/lib/web_ex/events/version.rb +5 -0
- data/spec/fixtures/responses/webex_events.xml +200 -0
- data/spec/fixtures/responses/webex_events_auth_error.xml +14 -0
- data/spec/fixtures/responses/webex_events_no_results.xml +14 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/web_ex/events/configuration_spec.rb +20 -0
- data/spec/web_ex/events/event_list_spec.rb +57 -0
- data/spec/web_ex/events/event_spec.rb +114 -0
- data/spec/web_ex/events/event_summary_request_spec.rb +137 -0
- data/web-ex-events.gemspec +30 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6313292bccf157b4ad36a2cbf03c81641e4bd024
|
4
|
+
data.tar.gz: 256e43c16759d10915bf1b80bf89ab29cb2404b8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d39ebb09c79cb01a8f18a02efcfe5645c67c7fce0ecaf3e549fa858fb078c4228407f010d5b4d4c482ab37a4cd3316414c6d3beff31d518bb9a1c8b182f0f408
|
7
|
+
data.tar.gz: 17931565713e2273947abc0298abbe5e123eb83ec66afc78ba0ccf5e5e8f7774b1384cf3f9414a2e01251257b3f1b6d945fdb5a44509bfc58e4b64d9d3d336e5
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Pete Nicholls
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# WebEx::Events
|
2
|
+
|
3
|
+
A library to read WebEx events through the WebEx API.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'web-ex-events'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install web-ex-events
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'web_ex/events'
|
23
|
+
|
24
|
+
# Set WebEx site name
|
25
|
+
ENV['WEB_EX_SITE_NAME'] = "…"
|
26
|
+
|
27
|
+
# Web Ex Site and Partner ID (available through WebEx support request)
|
28
|
+
ENV['WEB_EX_SITE_ID'] = "…"
|
29
|
+
ENV['WEB_EX_PARTNER_ID'] = "…"
|
30
|
+
|
31
|
+
# Your WebEx credentials
|
32
|
+
ENV['WEB_EX_USERNAME'] = "…"
|
33
|
+
ENV['WEB_EX_PASSWORD'] = "…"
|
34
|
+
|
35
|
+
next_30_days = 30 * 24 * 60 * 60
|
36
|
+
events = WebEx::Events::Event.fetch(next_30_days)
|
37
|
+
|
38
|
+
# Print event details
|
39
|
+
events.each do |event|
|
40
|
+
puts event.name
|
41
|
+
puts event.start_date
|
42
|
+
puts "#{event.duration} mins"
|
43
|
+
puts event.description
|
44
|
+
end
|
45
|
+
|
46
|
+
# Print all events as JSON
|
47
|
+
puts events.to_json
|
48
|
+
```
|
49
|
+
|
50
|
+
## Contributing
|
51
|
+
|
52
|
+
1. Fork it
|
53
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
54
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
55
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
56
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'httparty'
|
3
|
+
require 'tzinfo'
|
4
|
+
|
5
|
+
require "web_ex/events/version"
|
6
|
+
require "web_ex/events/configuration"
|
7
|
+
require "web_ex/events/event"
|
8
|
+
require "web_ex/events/event_list"
|
9
|
+
require "web_ex/events/event_summary_request"
|
10
|
+
require "web_ex/events/time_with_zone"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module WebEx
|
2
|
+
module Events
|
3
|
+
class Configuration
|
4
|
+
|
5
|
+
%w( site_name site_id username password partner_id ).each do |name|
|
6
|
+
define_singleton_method(name) { ENV["WEBEX_#{name.upcase}"] }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.xml_service_url
|
10
|
+
"https://#{site_name}.webex.com/WBXService/XMLService"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module WebEx
|
2
|
+
module Events
|
3
|
+
class Event
|
4
|
+
attr_accessor :name, :start_date, :end_date, :key, :description, :duration
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
attributes.each do |k, v|
|
8
|
+
send("#{k}=", v)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_json(*args)
|
13
|
+
JSON.dump(
|
14
|
+
name: name,
|
15
|
+
start_date: start_date,
|
16
|
+
end_date: end_date,
|
17
|
+
key: key,
|
18
|
+
description: description,
|
19
|
+
duration: duration
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_xml(xml)
|
24
|
+
node = Nokogiri::XML(xml)
|
25
|
+
element = node.xpath('event')
|
26
|
+
|
27
|
+
self.new(
|
28
|
+
name: element.xpath('sessionName').text,
|
29
|
+
start_date: TimeWithZone.new(element.xpath('startDate').text, element.xpath('timeZoneID').text).to_datetime,
|
30
|
+
end_date: TimeWithZone.new(element.xpath('endDate').text, element.xpath('timeZoneID').text).to_datetime,
|
31
|
+
key: element.xpath('sessionKey').text,
|
32
|
+
description: element.xpath('description').text,
|
33
|
+
duration: element.xpath('duration').text.to_i
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.fetch(time_frame)
|
38
|
+
request = EventSummaryRequest.new(start_date: Time.now, end_date: Time.now + time_frame)
|
39
|
+
request.find_events!
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module WebEx
|
2
|
+
module Events
|
3
|
+
class EventList
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(*events)
|
7
|
+
@events = events.flatten
|
8
|
+
end
|
9
|
+
|
10
|
+
def length
|
11
|
+
@events.length
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
@events.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def last
|
19
|
+
@events.last
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty?
|
23
|
+
@events.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_json
|
27
|
+
JSON.dump(@events)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module WebEx
|
2
|
+
module Events
|
3
|
+
class EventSummaryRequest
|
4
|
+
WEBEX_EMPTY_RESULTS_EXCEPTION_ID = "000015"
|
5
|
+
|
6
|
+
attr_accessor :start_date, :end_date
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@start_date, @end_date = options[:start_date], options[:end_date]
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_events!
|
13
|
+
events = xml_response.xpath('//event').map do |node|
|
14
|
+
Event.from_xml(node.to_xml)
|
15
|
+
end
|
16
|
+
|
17
|
+
EventList.new(events)
|
18
|
+
end
|
19
|
+
|
20
|
+
def payload
|
21
|
+
<<-XML
|
22
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
23
|
+
<message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
24
|
+
<header>
|
25
|
+
<securityContext>
|
26
|
+
<webExID>#{Configuration.username}</webExID>
|
27
|
+
<password>#{Configuration.password}</password>
|
28
|
+
<siteID>#{Configuration.site_id}</siteID>
|
29
|
+
<partnerID>#{Configuration.partner_id}</partnerID>
|
30
|
+
</securityContext>
|
31
|
+
</header>
|
32
|
+
<body>
|
33
|
+
<bodyContent xsi:type="java:com.webex.service.binding.event.LstsummaryEvent">
|
34
|
+
<listControl>
|
35
|
+
<startFrom/>
|
36
|
+
</listControl>
|
37
|
+
<order>
|
38
|
+
<orderBy>STARTTIME</orderBy>
|
39
|
+
</order>
|
40
|
+
<dateScope>
|
41
|
+
<startDateStart>#{formatted_date start_date}</startDateStart>
|
42
|
+
<endDateEnd>#{formatted_date end_date}</endDateEnd>
|
43
|
+
<timeZoneID>#{TimeWithZone::UTC_ZONE_ID}</timeZoneID>
|
44
|
+
</dateScope>
|
45
|
+
</bodyContent>
|
46
|
+
</body>
|
47
|
+
</message>
|
48
|
+
XML
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def response
|
54
|
+
@response ||= HTTParty.post(Configuration.xml_service_url, body: payload)
|
55
|
+
end
|
56
|
+
|
57
|
+
def xml_response
|
58
|
+
@xml_response ||= begin
|
59
|
+
xml = Nokogiri::XML(response.body)
|
60
|
+
webex_exception = xml.at_xpath('//serv:exceptionID')
|
61
|
+
|
62
|
+
if webex_exception && webex_exception.content != WEBEX_EMPTY_RESULTS_EXCEPTION_ID
|
63
|
+
raise "WebEx Error: #{xml.at_xpath('//serv:reason').content}"
|
64
|
+
end
|
65
|
+
|
66
|
+
xml.remove_namespaces!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def formatted_date(date)
|
71
|
+
date.utc.strftime('%m/%d/%Y %H:%M:%S') if date
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module WebEx
|
2
|
+
module Events
|
3
|
+
class TimeWithZone
|
4
|
+
UTC_ZONE_ID = 21
|
5
|
+
|
6
|
+
TIME_ZONE_MAPPINGS = {
|
7
|
+
0 => "Pacific/Niue",
|
8
|
+
1 => "Pacific/Apia",
|
9
|
+
2 => "Pacific/Honolulu",
|
10
|
+
3 => "America/Juneau ",
|
11
|
+
4 => "America/Los_Angeles",
|
12
|
+
5 => "America/Phoenixr",
|
13
|
+
6 => "America/Denver",
|
14
|
+
7 => "America/Chicago",
|
15
|
+
8 => "America/Tegucigalpa",
|
16
|
+
9 => "America/Regina",
|
17
|
+
10 => "America/Bogota",
|
18
|
+
11 => "America/New_York",
|
19
|
+
12 => "America/Indiana/Indianapolis",
|
20
|
+
13 => "America/Halifax",
|
21
|
+
14 => "America/Caracas",
|
22
|
+
15 => "America/St_Johns",
|
23
|
+
16 => "America/Sao_Paulo",
|
24
|
+
17 => "America/Argentina/Buenos_Aires",
|
25
|
+
18 => "Atlantic/South_Georgia",
|
26
|
+
19 => "Atlantic/Azores",
|
27
|
+
20 => "Africa/Casablanca",
|
28
|
+
21 => "Europe/London",
|
29
|
+
22 => "Europe/Amsterdam",
|
30
|
+
23 => "Europe/Paris",
|
31
|
+
24 => "Europe/Paris",
|
32
|
+
25 => "Europe/Berlin",
|
33
|
+
26 => "Europe/Athens",
|
34
|
+
27 => "Europe/Athens",
|
35
|
+
28 => "Africa/Cairo",
|
36
|
+
29 => "Africa/Johannesburg",
|
37
|
+
30 => "Europe/Helsinki",
|
38
|
+
31 => "Asia/Amman",
|
39
|
+
32 => "Asia/Baghdad",
|
40
|
+
33 => "Europe/Moscow",
|
41
|
+
34 => "Africa/Nairobi",
|
42
|
+
35 => "Asia/Tehran",
|
43
|
+
36 => "Asia/Muscat",
|
44
|
+
37 => "Asia/Baku",
|
45
|
+
38 => "Asia/Kabul",
|
46
|
+
39 => "Asia/Yekaterinburg",
|
47
|
+
40 => "Asia/Karachi",
|
48
|
+
41 => "Asia/Kolkata",
|
49
|
+
42 => "Asia/Colombo",
|
50
|
+
43 => "Asia/Almaty",
|
51
|
+
44 => "Asia/Bangkok",
|
52
|
+
45 => "Asia/Shanghai",
|
53
|
+
46 => "Australia/Perth",
|
54
|
+
47 => "Asia/Singapore",
|
55
|
+
48 => "Asia/Taipei",
|
56
|
+
49 => "Asia/Tokyo",
|
57
|
+
50 => "Asia/Seoul",
|
58
|
+
51 => "Asia/Yakutsk",
|
59
|
+
52 => "Australia/Adelaide",
|
60
|
+
53 => "Australia/Darwin",
|
61
|
+
54 => "Australia/Brisbane",
|
62
|
+
55 => "Australia/Sydney",
|
63
|
+
56 => "Pacific/Guam",
|
64
|
+
57 => "Australia/Hobart",
|
65
|
+
58 => "Asia/Vladivostok",
|
66
|
+
59 => "Asia/Magadan",
|
67
|
+
60 => "Pacific/Auckland",
|
68
|
+
61 => "Pacific/Fiji"
|
69
|
+
}
|
70
|
+
|
71
|
+
def initialize(date_string, timezone_id)
|
72
|
+
@date_string = date_string
|
73
|
+
@timezone_id = timezone_id.to_i
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_datetime
|
77
|
+
month, day, year, hour, minute, second = @date_string.split(/[\/ :]/).map(&:to_i)
|
78
|
+
time_zone = TZInfo::Timezone.get(TIME_ZONE_MAPPINGS[@timezone_id])
|
79
|
+
time_zone.local_to_utc DateTime.new(year, month, day, hour, minute, second)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
|
3
|
+
<serv:header>
|
4
|
+
<serv:response>
|
5
|
+
<serv:result>SUCCESS</serv:result>
|
6
|
+
<serv:gsbStatus>PRIMARY</serv:gsbStatus>
|
7
|
+
</serv:response>
|
8
|
+
</serv:header>
|
9
|
+
<serv:body>
|
10
|
+
<serv:bodyContent xsi:type="event:lstsummaryEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
11
|
+
<event:matchingRecords>
|
12
|
+
<serv:total>13</serv:total>
|
13
|
+
<serv:returned>13</serv:returned>
|
14
|
+
<serv:startFrom>1</serv:startFrom>
|
15
|
+
</event:matchingRecords>
|
16
|
+
<event:event>
|
17
|
+
<event:sessionKey>337167902</event:sessionKey>
|
18
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
19
|
+
<event:sessionType>220</event:sessionType>
|
20
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
21
|
+
<event:startDate>05/01/2013 05:00:00</event:startDate>
|
22
|
+
<event:endDate>05/01/2013 06:30:00</event:endDate>
|
23
|
+
<event:timeZoneID>4</event:timeZoneID>
|
24
|
+
<event:duration>90</event:duration>
|
25
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
26
|
+
<event:status>NOT_INPROGRESS</event:status>
|
27
|
+
<event:panelists></event:panelists>
|
28
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
29
|
+
</event:event>
|
30
|
+
<event:event>
|
31
|
+
<event:sessionKey>241299796</event:sessionKey>
|
32
|
+
<event:sessionName>Advanced Baking</event:sessionName>
|
33
|
+
<event:sessionType>220</event:sessionType>
|
34
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
35
|
+
<event:startDate>05/01/2013 08:00:00</event:startDate>
|
36
|
+
<event:endDate>05/01/2013 09:00:00</event:endDate>
|
37
|
+
<event:timeZoneID>4</event:timeZoneID>
|
38
|
+
<event:duration>60</event:duration>
|
39
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
40
|
+
<event:status>NOT_INPROGRESS</event:status>
|
41
|
+
<event:panelists>Satoshi Nakamoto</event:panelists>
|
42
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
43
|
+
</event:event>
|
44
|
+
<event:event>
|
45
|
+
<event:sessionKey>741475588</event:sessionKey>
|
46
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
47
|
+
<event:sessionType>220</event:sessionType>
|
48
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
49
|
+
<event:startDate>05/01/2013 11:00:00</event:startDate>
|
50
|
+
<event:endDate>05/01/2013 12:30:00</event:endDate>
|
51
|
+
<event:timeZoneID>4</event:timeZoneID>
|
52
|
+
<event:duration>90</event:duration>
|
53
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
54
|
+
<event:status>NOT_INPROGRESS</event:status>
|
55
|
+
<event:panelists></event:panelists>
|
56
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
57
|
+
</event:event>
|
58
|
+
<event:event>
|
59
|
+
<event:sessionKey>785125343</event:sessionKey>
|
60
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
61
|
+
<event:sessionType>220</event:sessionType>
|
62
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
63
|
+
<event:startDate>05/01/2013 13:00:00</event:startDate>
|
64
|
+
<event:endDate>05/01/2013 14:30:00</event:endDate>
|
65
|
+
<event:timeZoneID>4</event:timeZoneID>
|
66
|
+
<event:duration>90</event:duration>
|
67
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
68
|
+
<event:status>NOT_INPROGRESS</event:status>
|
69
|
+
<event:panelists></event:panelists>
|
70
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
71
|
+
</event:event>
|
72
|
+
<event:event>
|
73
|
+
<event:sessionKey>516377344</event:sessionKey>
|
74
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
75
|
+
<event:sessionType>220</event:sessionType>
|
76
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
77
|
+
<event:startDate>05/02/2013 05:00:00</event:startDate>
|
78
|
+
<event:endDate>05/02/2013 06:30:00</event:endDate>
|
79
|
+
<event:timeZoneID>4</event:timeZoneID>
|
80
|
+
<event:duration>90</event:duration>
|
81
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
82
|
+
<event:status>NOT_INPROGRESS</event:status>
|
83
|
+
<event:panelists></event:panelists>
|
84
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
85
|
+
</event:event>
|
86
|
+
<event:event>
|
87
|
+
<event:sessionKey>675735386</event:sessionKey>
|
88
|
+
<event:sessionName>Advanced Baking</event:sessionName>
|
89
|
+
<event:sessionType>220</event:sessionType>
|
90
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
91
|
+
<event:startDate>05/02/2013 08:00:00</event:startDate>
|
92
|
+
<event:endDate>05/02/2013 09:00:00</event:endDate>
|
93
|
+
<event:timeZoneID>4</event:timeZoneID>
|
94
|
+
<event:duration>60</event:duration>
|
95
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
96
|
+
<event:status>NOT_INPROGRESS</event:status>
|
97
|
+
<event:panelists>Satoshi Nakamoto</event:panelists>
|
98
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
99
|
+
</event:event>
|
100
|
+
<event:event>
|
101
|
+
<event:sessionKey>448544768</event:sessionKey>
|
102
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
103
|
+
<event:sessionType>220</event:sessionType>
|
104
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
105
|
+
<event:startDate>05/02/2013 11:00:00</event:startDate>
|
106
|
+
<event:endDate>05/02/2013 12:30:00</event:endDate>
|
107
|
+
<event:timeZoneID>4</event:timeZoneID>
|
108
|
+
<event:duration>90</event:duration>
|
109
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
110
|
+
<event:status>NOT_INPROGRESS</event:status>
|
111
|
+
<event:panelists></event:panelists>
|
112
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
113
|
+
</event:event>
|
114
|
+
<event:event>
|
115
|
+
<event:sessionKey>548465686</event:sessionKey>
|
116
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
117
|
+
<event:sessionType>220</event:sessionType>
|
118
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
119
|
+
<event:startDate>05/02/2013 13:00:00</event:startDate>
|
120
|
+
<event:endDate>05/02/2013 14:30:00</event:endDate>
|
121
|
+
<event:timeZoneID>4</event:timeZoneID>
|
122
|
+
<event:duration>90</event:duration>
|
123
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
124
|
+
<event:status>NOT_INPROGRESS</event:status>
|
125
|
+
<event:panelists></event:panelists>
|
126
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
127
|
+
</event:event>
|
128
|
+
<event:event>
|
129
|
+
<event:sessionKey>265268976</event:sessionKey>
|
130
|
+
<event:sessionName>Advanced Baking</event:sessionName>
|
131
|
+
<event:sessionType>220</event:sessionType>
|
132
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
133
|
+
<event:startDate>05/03/2013 08:00:00</event:startDate>
|
134
|
+
<event:endDate>05/03/2013 09:00:00</event:endDate>
|
135
|
+
<event:timeZoneID>4</event:timeZoneID>
|
136
|
+
<event:duration>60</event:duration>
|
137
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
138
|
+
<event:status>NOT_INPROGRESS</event:status>
|
139
|
+
<event:panelists>Satoshi Nakamoto</event:panelists>
|
140
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
141
|
+
</event:event>
|
142
|
+
<event:event>
|
143
|
+
<event:sessionKey>223574221</event:sessionKey>
|
144
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
145
|
+
<event:sessionType>220</event:sessionType>
|
146
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
147
|
+
<event:startDate>05/07/2013 05:00:00</event:startDate>
|
148
|
+
<event:endDate>05/07/2013 06:30:00</event:endDate>
|
149
|
+
<event:timeZoneID>4</event:timeZoneID>
|
150
|
+
<event:duration>90</event:duration>
|
151
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
152
|
+
<event:status>NOT_INPROGRESS</event:status>
|
153
|
+
<event:panelists></event:panelists>
|
154
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
155
|
+
</event:event>
|
156
|
+
<event:event>
|
157
|
+
<event:sessionKey>495477388</event:sessionKey>
|
158
|
+
<event:sessionName>Advanced Baking</event:sessionName>
|
159
|
+
<event:sessionType>220</event:sessionType>
|
160
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
161
|
+
<event:startDate>05/07/2013 11:00:00</event:startDate>
|
162
|
+
<event:endDate>05/07/2013 12:00:00</event:endDate>
|
163
|
+
<event:timeZoneID>4</event:timeZoneID>
|
164
|
+
<event:duration>60</event:duration>
|
165
|
+
<event:description>Learn advanced Japanese baking techniques in this hour-long webinar.</event:description>
|
166
|
+
<event:status>NOT_INPROGRESS</event:status>
|
167
|
+
<event:panelists></event:panelists>
|
168
|
+
<event:listStatus>PUBLIC</event:listStatus>
|
169
|
+
</event:event>
|
170
|
+
<event:event>
|
171
|
+
<event:sessionKey>252653476</event:sessionKey>
|
172
|
+
<event:sessionName>Baking Basics</event:sessionName>
|
173
|
+
<event:sessionType>220</event:sessionType>
|
174
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
175
|
+
<event:startDate>05/07/2013 11:00:00</event:startDate>
|
176
|
+
<event:endDate>05/07/2013 12:30:00</event:endDate>
|
177
|
+
<event:timeZoneID>4</event:timeZoneID>
|
178
|
+
<event:duration>90</event:duration>
|
179
|
+
<event:description>Learn the intricacies of Japanese baking in this 90 minute webinar.</event:description>
|
180
|
+
<event:status>NOT_INPROGRESS</event:status>
|
181
|
+
<event:panelists></event:panelists>
|
182
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
183
|
+
</event:event>
|
184
|
+
<event:event>
|
185
|
+
<event:sessionKey>356727241</event:sessionKey>
|
186
|
+
<event:sessionName>Baking Finale</event:sessionName>
|
187
|
+
<event:sessionType>220</event:sessionType>
|
188
|
+
<event:hostWebExID>bakery</event:hostWebExID>
|
189
|
+
<event:startDate>05/07/2013 13:00:00</event:startDate>
|
190
|
+
<event:endDate>05/07/2013 14:30:00</event:endDate>
|
191
|
+
<event:timeZoneID>4</event:timeZoneID>
|
192
|
+
<event:duration>90</event:duration>
|
193
|
+
<event:description>A 90 minute wrap-up event!</event:description>
|
194
|
+
<event:status>NOT_INPROGRESS</event:status>
|
195
|
+
<event:panelists></event:panelists>
|
196
|
+
<event:listStatus>UNLISTED</event:listStatus>
|
197
|
+
</event:event>
|
198
|
+
</serv:bodyContent>
|
199
|
+
</serv:body>
|
200
|
+
</serv:message>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
|
3
|
+
<serv:header>
|
4
|
+
<serv:response>
|
5
|
+
<serv:result>FAILURE</serv:result>
|
6
|
+
<serv:reason>Corresponding User not found</serv:reason>
|
7
|
+
<serv:gsbStatus>PRIMARY</serv:gsbStatus>
|
8
|
+
<serv:exceptionID>030001</serv:exceptionID>
|
9
|
+
</serv:response>
|
10
|
+
</serv:header>
|
11
|
+
<serv:body>
|
12
|
+
<serv:bodyContent/>
|
13
|
+
</serv:body>
|
14
|
+
</serv:message>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
|
3
|
+
<serv:header>
|
4
|
+
<serv:response>
|
5
|
+
<serv:result>FAILURE</serv:result>
|
6
|
+
<serv:reason>Sorry, no record found</serv:reason>
|
7
|
+
<serv:gsbStatus>PRIMARY</serv:gsbStatus>
|
8
|
+
<serv:exceptionID>000015</serv:exceptionID>
|
9
|
+
</serv:response>
|
10
|
+
</serv:header>
|
11
|
+
<serv:body>
|
12
|
+
<serv:bodyContent/>
|
13
|
+
</serv:body>
|
14
|
+
</serv:message>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Configuration do
|
4
|
+
context "with all environment variables present" do
|
5
|
+
before :each do
|
6
|
+
ENV.stub(:[]).with("WEBEX_SITE_NAME").and_return("bakeryevents")
|
7
|
+
ENV.stub(:[]).with("WEBEX_USERNAME").and_return("bakery")
|
8
|
+
ENV.stub(:[]).with("WEBEX_PASSWORD").and_return("secret")
|
9
|
+
ENV.stub(:[]).with("WEBEX_SITE_ID").and_return("358562")
|
10
|
+
ENV.stub(:[]).with("WEBEX_PARTNER_ID").and_return("123ab")
|
11
|
+
end
|
12
|
+
|
13
|
+
it { Configuration.site_name.should == "bakeryevents" }
|
14
|
+
it { Configuration.username.should == "bakery" }
|
15
|
+
it { Configuration.password.should == "secret" }
|
16
|
+
it { Configuration.site_id.should == "358562" }
|
17
|
+
it { Configuration.partner_id.should == "123ab" }
|
18
|
+
it { Configuration.xml_service_url.should == "https://bakeryevents.webex.com/WBXService/XMLService" }
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EventList do
|
4
|
+
let(:event_a) { stub }
|
5
|
+
let(:event_b) { stub }
|
6
|
+
let(:event_c) { stub }
|
7
|
+
|
8
|
+
describe "#each" do
|
9
|
+
let(:event_list) { EventList.new(event_a, event_b, event_c) }
|
10
|
+
|
11
|
+
it "iterates over each event" do
|
12
|
+
captured_events = []
|
13
|
+
event_list.each { |event| captured_events << event }
|
14
|
+
captured_events.should == [event_a, event_b, event_c]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#to_json" do
|
19
|
+
let(:event_list) { EventList.new(event_a, event_b) }
|
20
|
+
|
21
|
+
before :each do
|
22
|
+
event_a.stub(to_json: '{ "event": "a" }')
|
23
|
+
event_b.stub(to_json: '{ "event": "b" }')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns a JSON representation of all events" do
|
27
|
+
JSON.parse(event_list.to_json).should == [{ 'event' => 'a' }, { 'event' => 'b' }]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#length" do
|
32
|
+
it "returns the number of events" do
|
33
|
+
EventList.new(event_a, event_b).length.should == 2
|
34
|
+
EventList.new(event_a, event_b, event_c).length.should == 3
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with three events" do
|
39
|
+
let(:event_list) { EventList.new(event_a, event_b, event_c) }
|
40
|
+
|
41
|
+
describe "#first and #last" do
|
42
|
+
it { event_list.first.should == event_a }
|
43
|
+
it { event_list.last.should == event_c }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with no events" do
|
48
|
+
subject { EventList.new }
|
49
|
+
it { should be_empty }
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with at least one event" do
|
53
|
+
subject { EventList.new(event_a) }
|
54
|
+
it { should_not be_empty }
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Event do
|
4
|
+
let(:valid_attributes) {
|
5
|
+
{
|
6
|
+
name: "Cupcake Giveaway",
|
7
|
+
start_date: DateTime.now,
|
8
|
+
end_date: DateTime.now + 3600,
|
9
|
+
key: "12345",
|
10
|
+
description: "Free cupcakes!",
|
11
|
+
duration: 60
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:event) { Event.new(valid_attributes) }
|
16
|
+
|
17
|
+
it "can has accessors for valid attributes" do
|
18
|
+
valid_attributes.each do |name, value|
|
19
|
+
event.send(name).should == value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#to_json" do
|
24
|
+
let(:json) { JSON.parse(event.to_json) }
|
25
|
+
|
26
|
+
it "contains all the valid attributes" do
|
27
|
+
json["name"].should == "Cupcake Giveaway"
|
28
|
+
json["start_date"].inspect.should == JSON.dump(DateTime.now)
|
29
|
+
json["end_date"].inspect.should == JSON.dump(DateTime.now + 3600)
|
30
|
+
json["key"].should == "12345"
|
31
|
+
json["duration"].should == 60
|
32
|
+
json["description"].should == "Free cupcakes!"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".from_xml" do
|
37
|
+
let(:xml) {
|
38
|
+
<<-XML
|
39
|
+
<event>
|
40
|
+
<sessionKey>662050914</sessionKey>
|
41
|
+
<sessionName>NE Utilities - Transition Webinar Navtrak to Fleet</sessionName>
|
42
|
+
<sessionType>220</sessionType>
|
43
|
+
<hostWebExID>bakery</hostWebExID>
|
44
|
+
<startDate>04/30/2013 05:00:00</startDate>
|
45
|
+
<endDate>04/30/2013 06:30:00</endDate>
|
46
|
+
<timeZoneID>4</timeZoneID>
|
47
|
+
<duration>90</duration>
|
48
|
+
<description>During this webinar you will be trained on the bakery Fleet application.</description>
|
49
|
+
<status>NOT_INPROGRESS</status>
|
50
|
+
<panelists></panelists>
|
51
|
+
<listStatus>UNLISTED</listStatus>
|
52
|
+
</event>
|
53
|
+
XML
|
54
|
+
}
|
55
|
+
|
56
|
+
let(:parsed_event) { Event.from_xml(xml) }
|
57
|
+
|
58
|
+
it "can parse an event" do
|
59
|
+
parsed_event.name.should == "NE Utilities - Transition Webinar Navtrak to Fleet"
|
60
|
+
parsed_event.key.should == "662050914"
|
61
|
+
parsed_event.duration.should == 90
|
62
|
+
parsed_event.description.should == "During this webinar you will be trained on the bakery Fleet application."
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with a timezone not in daylight savings" do
|
66
|
+
let(:xml) {
|
67
|
+
<<-XML
|
68
|
+
<event>
|
69
|
+
<startDate>02/15/2013 05:00:00</startDate>
|
70
|
+
<endDate>02/15/2013 06:30:00</endDate>
|
71
|
+
<timeZoneID>4</timeZoneID>
|
72
|
+
</event>
|
73
|
+
XML
|
74
|
+
}
|
75
|
+
|
76
|
+
it "parses the date correctly" do
|
77
|
+
parsed_event.start_date.should == DateTime.new(2013, 2, 15, 5, 0, 0, "-08:00")
|
78
|
+
parsed_event.end_date.should == DateTime.new(2013, 2, 15, 6, 30, 0, "-08:00")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with a timezone inside daylight savings" do
|
83
|
+
let(:xml) {
|
84
|
+
<<-XML
|
85
|
+
<event>
|
86
|
+
<startDate>04/30/2013 05:00:00</startDate>
|
87
|
+
<endDate>04/30/2013 06:30:00</endDate>
|
88
|
+
<timeZoneID>4</timeZoneID>
|
89
|
+
</event>
|
90
|
+
XML
|
91
|
+
}
|
92
|
+
|
93
|
+
it "corrects for daylight savings" do
|
94
|
+
parsed_event.start_date.should == DateTime.new(2013, 4, 30, 5, 0, 0, "-07:00")
|
95
|
+
parsed_event.end_date.should == DateTime.new(2013, 4, 30, 6, 30, 0, "-07:00")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe ".fetch" do
|
101
|
+
it "creates a new event summary request using the time frame" do
|
102
|
+
Timecop.freeze do
|
103
|
+
request = stub(find_events!: "events")
|
104
|
+
ten_days = 10 * 24 * 60 * 60
|
105
|
+
|
106
|
+
EventSummaryRequest.should_receive(:new)
|
107
|
+
.with(start_date: Time.now, end_date: Time.now + ten_days)
|
108
|
+
.and_return(request)
|
109
|
+
|
110
|
+
Event.fetch(ten_days).should == "events"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fakeweb'
|
3
|
+
|
4
|
+
describe EventSummaryRequest do
|
5
|
+
def fixture_path(name)
|
6
|
+
File.expand_path("../../../fixtures/#{name}", __FILE__)
|
7
|
+
end
|
8
|
+
|
9
|
+
context "with a start date of a day ago and end date in a weeks' time" do
|
10
|
+
let(:one_second) { 1 }
|
11
|
+
let(:one_day_ago) { Time.now - (24 * 60 * 60) }
|
12
|
+
let(:seven_days_from_now) { Time.now + (7 * 24 * 60 * 60) }
|
13
|
+
|
14
|
+
let(:req) { EventSummaryRequest.new(start_date: one_day_ago, end_date: seven_days_from_now) }
|
15
|
+
|
16
|
+
describe "#start_date" do
|
17
|
+
subject { req.start_date }
|
18
|
+
it { should be_within(one_second).of(one_day_ago) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#end_date" do
|
22
|
+
subject { req.end_date }
|
23
|
+
it { should be_within(one_second).of(seven_days_from_now) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#payload" do
|
28
|
+
let(:req) { EventSummaryRequest.new }
|
29
|
+
let(:xml) { Nokogiri::XML(req.payload) }
|
30
|
+
|
31
|
+
describe "<?xml ?> processing instruction" do
|
32
|
+
subject { xml.at_xpath('/processing-instruction("xml")').content }
|
33
|
+
it { should include("UTF-8") }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "namespaces" do
|
37
|
+
let(:namespaces) { xml.collect_namespaces }
|
38
|
+
it { namespaces.should have_key('xmlns:xsi') }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "security context" do
|
42
|
+
before :each do
|
43
|
+
Configuration.stub(
|
44
|
+
site_name: "wafflehut",
|
45
|
+
site_id: "12345",
|
46
|
+
username: "bobwaffles",
|
47
|
+
password: "maplesyrup",
|
48
|
+
partner_id: "p4rtn3r"
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:security_context) { xml.at_xpath('/message/header/securityContext') }
|
53
|
+
it { security_context.at_xpath('./webExID').content.should == "bobwaffles" }
|
54
|
+
it { security_context.at_xpath('./password').content.should == "maplesyrup" }
|
55
|
+
it { security_context.at_xpath('./siteID').content.should == "12345" }
|
56
|
+
it { security_context.at_xpath('./partnerID').content.should == "p4rtn3r" }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "body content" do
|
60
|
+
let(:body_content) { xml.at_xpath('/message/body/bodyContent') }
|
61
|
+
it { body_content['xsi:type'].should include('LstsummaryEvent') }
|
62
|
+
it { body_content.at_xpath('./listControl/startFrom').should_not be_nil }
|
63
|
+
it { body_content.at_xpath('./order').should_not be_nil }
|
64
|
+
it { body_content.at_xpath('./dateScope').should_not be_nil }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with start and end dates in a time zone" do
|
68
|
+
before :each do
|
69
|
+
midday_pancake_tuesday = Time.new(2014, 3, 4, 12, 0, 0, "+02:00")
|
70
|
+
three_thirty_pm_pancake_tuesday = Time.new(2014, 3, 4, 15, 30, 0, "+02:00")
|
71
|
+
req.stub(start_date: midday_pancake_tuesday, end_date: three_thirty_pm_pancake_tuesday)
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "date scope" do
|
75
|
+
let(:date_scope) { xml.at_xpath('/message/body/bodyContent/dateScope') }
|
76
|
+
|
77
|
+
it "formats dates appropriately and in UTC time" do
|
78
|
+
date_scope.at_xpath('./startDateStart').content.should == "03/04/2014 10:00:00"
|
79
|
+
date_scope.at_xpath('./endDateEnd').content.should == "03/04/2014 13:30:00"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "uses the UTC time zone ID" do
|
83
|
+
date_scope.at_xpath('./timeZoneID').content.should == "21"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#find_events!" do
|
90
|
+
let(:req) { EventSummaryRequest.new }
|
91
|
+
|
92
|
+
before :each do
|
93
|
+
Configuration.stub(xml_service_url: "https://webex-api.example.com/service")
|
94
|
+
FakeWeb.register_uri(:post, "https://webex-api.example.com/service", body: response_body)
|
95
|
+
req.stub(payload: "XML")
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when the server responds with events" do
|
99
|
+
let(:response_body) { fixture_path("responses/webex_events.xml") }
|
100
|
+
|
101
|
+
it "creates a new event using from each event node" do
|
102
|
+
Event.should_receive(:from_xml).exactly(13).times
|
103
|
+
req.find_events!
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns the events in an event list" do
|
107
|
+
events = req.find_events!
|
108
|
+
events.should be_a(EventList)
|
109
|
+
events.length.should == 13
|
110
|
+
events.first.name.should == "Baking Basics"
|
111
|
+
events.last.name.should == "Baking Finale"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "when the server responds without events" do
|
116
|
+
let(:response_body) { fixture_path("responses/webex_events_no_results.xml") }
|
117
|
+
|
118
|
+
it "returns an empty list" do
|
119
|
+
events = req.find_events!
|
120
|
+
events.should be_a(EventList)
|
121
|
+
events.should be_empty
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when the server responds with an authentication error" do
|
126
|
+
let(:response_body) { fixture_path("responses/webex_events_auth_error.xml") }
|
127
|
+
|
128
|
+
it "raises an error with the server's reason for the error" do
|
129
|
+
-> {
|
130
|
+
req.find_events!
|
131
|
+
}.should raise_error { |error|
|
132
|
+
error.message.should include('Corresponding User not found')
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'web_ex/events/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "web-ex-events"
|
8
|
+
spec.version = WebEx::Events::VERSION
|
9
|
+
spec.authors = ["Pete Nicholls"]
|
10
|
+
spec.email = ["pete@metanation.com"]
|
11
|
+
spec.description = "Allows fetching and parsing WebEx events through the WebEx API. Events can be queried and converted into JSON."
|
12
|
+
spec.summary = "A library to read WebEx events through the WebEx API."
|
13
|
+
spec.homepage = "https://github.com/Aupajo/web-ex-events"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "timecop"
|
25
|
+
spec.add_development_dependency "fakeweb"
|
26
|
+
|
27
|
+
spec.add_dependency "tzinfo"
|
28
|
+
spec.add_dependency "httparty"
|
29
|
+
spec.add_dependency "nokogiri"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: web-ex-events
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pete Nicholls
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: timecop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakeweb
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: tzinfo
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: httparty
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: nokogiri
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Allows fetching and parsing WebEx events through the WebEx API. Events
|
126
|
+
can be queried and converted into JSON.
|
127
|
+
email:
|
128
|
+
- pete@metanation.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- lib/web_ex/events.rb
|
139
|
+
- lib/web_ex/events/configuration.rb
|
140
|
+
- lib/web_ex/events/event.rb
|
141
|
+
- lib/web_ex/events/event_list.rb
|
142
|
+
- lib/web_ex/events/event_summary_request.rb
|
143
|
+
- lib/web_ex/events/time_with_zone.rb
|
144
|
+
- lib/web_ex/events/version.rb
|
145
|
+
- spec/fixtures/responses/webex_events.xml
|
146
|
+
- spec/fixtures/responses/webex_events_auth_error.xml
|
147
|
+
- spec/fixtures/responses/webex_events_no_results.xml
|
148
|
+
- spec/spec_helper.rb
|
149
|
+
- spec/web_ex/events/configuration_spec.rb
|
150
|
+
- spec/web_ex/events/event_list_spec.rb
|
151
|
+
- spec/web_ex/events/event_spec.rb
|
152
|
+
- spec/web_ex/events/event_summary_request_spec.rb
|
153
|
+
- web-ex-events.gemspec
|
154
|
+
homepage: https://github.com/Aupajo/web-ex-events
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata: {}
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
require_paths:
|
161
|
+
- lib
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.0.3
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: A library to read WebEx events through the WebEx API.
|
178
|
+
test_files:
|
179
|
+
- spec/fixtures/responses/webex_events.xml
|
180
|
+
- spec/fixtures/responses/webex_events_auth_error.xml
|
181
|
+
- spec/fixtures/responses/webex_events_no_results.xml
|
182
|
+
- spec/spec_helper.rb
|
183
|
+
- spec/web_ex/events/configuration_spec.rb
|
184
|
+
- spec/web_ex/events/event_list_spec.rb
|
185
|
+
- spec/web_ex/events/event_spec.rb
|
186
|
+
- spec/web_ex/events/event_summary_request_spec.rb
|