cherby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/.yardopts +4 -0
- data/Gemfile +6 -0
- data/README.md +83 -0
- data/Rakefile +12 -0
- data/cherby.gemspec +29 -0
- data/lib/cherby.rb +11 -0
- data/lib/cherby/business_object.rb +159 -0
- data/lib/cherby/cherwell.rb +230 -0
- data/lib/cherby/client.rb +147 -0
- data/lib/cherby/exceptions.rb +6 -0
- data/lib/cherby/incident.rb +141 -0
- data/lib/cherby/journal_note.rb +13 -0
- data/lib/cherby/task.rb +37 -0
- data/lib/cherby/templates/incident.mustache +226 -0
- data/lib/cherby/templates/journal_note.mustache +30 -0
- data/lib/cherby/templates/journal_note_relationship.mustache +3 -0
- data/lib/cherby/templates/task.mustache +67 -0
- data/lib/cherby/templates/task_relationship.mustache +3 -0
- data/lib/cherby/templates/test/simple.mustache +8 -0
- data/spec/business_object_spec.rb +250 -0
- data/spec/cherwell_spec.rb +300 -0
- data/spec/client_spec.rb +149 -0
- data/spec/data/cherwell.wsdl +1568 -0
- data/spec/data/incident.xml +1411 -0
- data/spec/data/login_false.xml +8 -0
- data/spec/data/login_true.xml +6 -0
- data/spec/data/task.xml +64 -0
- data/spec/incident_spec.rb +124 -0
- data/spec/journal_note_spec.rb +13 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/task_spec.rb +77 -0
- data/spec/xml/method_response_result.mustache +4 -0
- data/spec/xml/soap_envelope.mustache +6 -0
- data/tasks/pry.rake +28 -0
- data/tasks/spec.rake +8 -0
- metadata +261 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<BusinessObject Name="JournalNote" RecID="{{rec_id}}">
|
3
|
+
<FieldList>
|
4
|
+
<!-- Fields common to all BusinessObjects -->
|
5
|
+
<Field Name="RecID">{{rec_id}}</Field>
|
6
|
+
<Field Name="CreatedDateTime">{{created_date_time}}</Field>
|
7
|
+
<Field Name="CreatedBy">{{created_by}}</Field>
|
8
|
+
<Field Name="CreatedByID"></Field>
|
9
|
+
<Field Name="LastModDateTime">{{last_mod_date_time}}</Field>
|
10
|
+
<Field Name="LastModBy">{{last_mod_by}}</Field>
|
11
|
+
<Field Name="LastModByID"></Field>
|
12
|
+
<Field Name="OwnedBy">{{owned_by}}</Field>
|
13
|
+
<Field Name="OwnedByTeam">{{owned_by_team}}</Field>
|
14
|
+
<Field Name="OwnerID"></Field>
|
15
|
+
<Field Name="OwnerTeamID"></Field>
|
16
|
+
<!-- Unused fields? -->
|
17
|
+
<Field Name="LastModTimeStamp"/>
|
18
|
+
|
19
|
+
<Field Name="JournalTypeID">{{journal_type_id}}</Field>
|
20
|
+
<Field Name="JournalTypeName">Note</Field>
|
21
|
+
<Field Name="ParentTypeID">{{parent_type_id}}</Field>
|
22
|
+
<Field Name="ParentRecordID">{{parent_record_id}}</Field>
|
23
|
+
<Field Name="Details">{{details}}</Field>
|
24
|
+
<Field Name="Priority">Normal</Field>
|
25
|
+
<Field Name="ShowInSelfService">TRUE</Field>
|
26
|
+
<Field Name="QuickJournal"/>
|
27
|
+
<Field Name="IncomingEmail">FALSE</Field>
|
28
|
+
</FieldList>
|
29
|
+
</BusinessObject>
|
30
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<BusinessObject Name="Task" RecID="{{rec_id}}">
|
3
|
+
<FieldList>
|
4
|
+
<!-- Fields common to all BusinessObjects -->
|
5
|
+
<Field Name="RecID">{{rec_id}}</Field>
|
6
|
+
<Field Name="CreatedDateTime">{{created_date_time}}</Field>
|
7
|
+
<Field Name="CreatedBy">{{created_by}}</Field>
|
8
|
+
<Field Name="CreatedByID"></Field>
|
9
|
+
<Field Name="LastModDateTime">{{last_mod_date_time}}</Field>
|
10
|
+
<Field Name="LastModBy">{{last_mod_by}}</Field>
|
11
|
+
<Field Name="LastModByID"></Field>
|
12
|
+
<Field Name="OwnedBy">{{owned_by}}</Field>
|
13
|
+
<Field Name="OwnedByTeam">{{owned_by_team}}</Field>
|
14
|
+
<Field Name="OwnerID"></Field>
|
15
|
+
<Field Name="OwnerTeamID"></Field>
|
16
|
+
<!-- Unused fields? -->
|
17
|
+
<Field Name="LastModTimeStamp"/>
|
18
|
+
|
19
|
+
<Field Name="TaskType">Action</Field>
|
20
|
+
<Field Name="TaskDescription">{{task_description}}</Field>
|
21
|
+
<Field Name="StartDateTime">{{start_date_time}}</Field>
|
22
|
+
<Field Name="ParentID">{{parent_id}}</Field>
|
23
|
+
<Field Name="ParentTypeID">{{parent_type_id}}</Field>
|
24
|
+
<Field Name="AssignedToID"></Field>
|
25
|
+
<Field Name="AssignedTo"></Field>
|
26
|
+
<Field Name="AssignedToTeamID"></Field>
|
27
|
+
<Field Name="AssignedToTeam"></Field>
|
28
|
+
<Field Name="Notes">{{notes}}</Field>
|
29
|
+
<Field Name="AcknowledgedByID"></Field>
|
30
|
+
<Field Name="AcknowledgedBy"></Field>
|
31
|
+
<Field Name="AcknowledgedDateTime">0001-01-01T00:00:00</Field>
|
32
|
+
<Field Name="AcknowledgedComment"></Field>
|
33
|
+
<Field Name="ResolvedByID"></Field>
|
34
|
+
<Field Name="ResolvedBy"></Field>
|
35
|
+
<Field Name="ResolvedDateTime">0001-01-01T00:00:00</Field>
|
36
|
+
<Field Name="ResolutionCode">{{resolution_code}}</Field>
|
37
|
+
<Field Name="CompletionDetails">{{completion_details}}</Field>
|
38
|
+
<Field Name="TaskDurationInHours">0.00</Field>
|
39
|
+
<Field Name="Status">{{status}}</Field>
|
40
|
+
<Field Name="Availabiltiy"></Field>
|
41
|
+
<Field Name="Email"></Field>
|
42
|
+
<Field Name="Phone"></Field>
|
43
|
+
<Field Name="CellPhone"></Field>
|
44
|
+
<Field Name="LimitAssigneeByTeam"></Field>
|
45
|
+
<Field Name="ParentTypeName">Incident</Field>
|
46
|
+
<Field Name="ParentPublicID">{{parent_public_id}}</Field>
|
47
|
+
<Field Name="TaskOrder">0.00</Field>
|
48
|
+
<Field Name="ParentActivity"></Field>
|
49
|
+
<Field Name="ActivityOrder">0</Field>
|
50
|
+
<Field Name="ParentActivityOrder">0</Field>
|
51
|
+
<Field Name="DependsOnName"></Field>
|
52
|
+
<Field Name="DependsOnID"></Field>
|
53
|
+
<Field Name="TaskActive">TRUE</Field>
|
54
|
+
<Field Name="DependsOnStatus"></Field>
|
55
|
+
<Field Name="Name"></Field>
|
56
|
+
<Field Name="EndDateTime">{{end_date_time}}</Field>
|
57
|
+
<Field Name="Location"></Field>
|
58
|
+
<Field Name="OwnedByNonCherwellUser">FALSE</Field>
|
59
|
+
<Field Name="TaskID">{{task_id}}</Field>
|
60
|
+
<Field Name="OwnedByEmail">{{owned_by_email}}</Field>
|
61
|
+
<Field Name="TeamNotified">FALSE</Field>
|
62
|
+
<Field Name="ActiveBy"></Field>
|
63
|
+
<Field Name="ActiveByID"></Field>
|
64
|
+
<Field Name="ActiveDateTime">0001-01-01T00:00:00</Field>
|
65
|
+
<Field Name="CreatedByCustomer">FALSE</Field>
|
66
|
+
</FieldList>
|
67
|
+
</BusinessObject>
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'cherby/business_object'
|
3
|
+
|
4
|
+
# Some BusinessObject subclasses to test with
|
5
|
+
class MySubclass < Cherby::BusinessObject
|
6
|
+
@object_name = 'MySubclass'
|
7
|
+
@template = 'test/simple'
|
8
|
+
@default_values = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
class MySubclassNoTemplate < Cherby::BusinessObject
|
12
|
+
@object_name = 'MySubclassNoTemplate'
|
13
|
+
@template = ''
|
14
|
+
@default_values = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
class MySubclassNoTemplateFile < Cherby::BusinessObject
|
18
|
+
@object_name = 'MySubclassNoTemplateFile'
|
19
|
+
@template = 'no_such_file'
|
20
|
+
@default_values = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Cherby::BusinessObject do
|
24
|
+
context "Class methods" do
|
25
|
+
describe "#create" do
|
26
|
+
it "sets options in the DOM" do
|
27
|
+
obj = MySubclass.create({:first_name => 'Eric', :last_name => 'Idle'})
|
28
|
+
first_name = obj.dom.css("BusinessObject[@Name=MySubclass] Field[@Name=First]").first
|
29
|
+
last_name = obj.dom.css("BusinessObject[@Name=MySubclass] Field[@Name=Last]").first
|
30
|
+
first_name.content.should == "Eric"
|
31
|
+
last_name.content.should == "Idle"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises an exception when no template is provided" do
|
35
|
+
lambda do
|
36
|
+
MySubclassNoTemplate.create
|
37
|
+
end.should raise_error(RuntimeError, /No template defined/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "raises an exception if the template file is nonexistent" do
|
41
|
+
lambda do
|
42
|
+
MySubclassNoTemplateFile.create
|
43
|
+
end.should raise_error(Errno::ENOENT, /No such file/)
|
44
|
+
end
|
45
|
+
end #create
|
46
|
+
|
47
|
+
describe "#parse_datetime" do
|
48
|
+
it "works with timezone offset" do
|
49
|
+
bo = Cherby::BusinessObject
|
50
|
+
dt = bo.parse_datetime("2012-02-09T09:42:13-05:00")
|
51
|
+
dt.to_s.should == "2012-02-09T14:42:13+00:00"
|
52
|
+
|
53
|
+
dt = bo.parse_datetime("2012-02-09T09:42:13.123-0500")
|
54
|
+
dt.to_s.should == "2012-02-09T14:42:13+00:00"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "works without timezone offset" do
|
58
|
+
bo = Cherby::BusinessObject
|
59
|
+
dt = bo.parse_datetime("2012-02-09T09:42:13", -5)
|
60
|
+
dt.to_s.should == "2012-02-09T14:42:13+00:00"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises ArgumentError for invalid datetime string" do
|
64
|
+
bo = Cherby::BusinessObject
|
65
|
+
lambda do
|
66
|
+
bo.parse_datetime("bogus-datetime")
|
67
|
+
end.should raise_error(ArgumentError, /Could not parse/)
|
68
|
+
end
|
69
|
+
|
70
|
+
end #parse_datetime
|
71
|
+
|
72
|
+
end # Class methods
|
73
|
+
|
74
|
+
|
75
|
+
context "Instance methods" do
|
76
|
+
describe "#initialize" do
|
77
|
+
it "accepts an XML string" do
|
78
|
+
xml = %Q{
|
79
|
+
<BusinessObject Name="MySubclass">
|
80
|
+
<FieldList>
|
81
|
+
<Field Name="First">Eric</Field>
|
82
|
+
<Field Name="Last">Idle</Field>
|
83
|
+
</FieldList>
|
84
|
+
</BusinessObject>
|
85
|
+
}
|
86
|
+
obj = MySubclass.new(xml)
|
87
|
+
first_name = obj.dom.css("BusinessObject[@Name=MySubclass] Field[@Name=First]").first
|
88
|
+
last_name = obj.dom.css("BusinessObject[@Name=MySubclass] Field[@Name=Last]").first
|
89
|
+
first_name.content.should == "Eric"
|
90
|
+
last_name.content.should == "Idle"
|
91
|
+
end
|
92
|
+
|
93
|
+
end #initialize
|
94
|
+
|
95
|
+
describe "#[]" do
|
96
|
+
it "returns the value in the named field" do
|
97
|
+
obj = MySubclass.create({:first_name => 'Eric', :last_name => 'Idle'})
|
98
|
+
obj['First'].should == 'Eric'
|
99
|
+
obj['Last'].should == 'Idle'
|
100
|
+
end
|
101
|
+
end #[]
|
102
|
+
|
103
|
+
describe "#[]=" do
|
104
|
+
it "puts a value in the named field" do
|
105
|
+
obj = MySubclass.create({:first_name => 'Eric', :last_name => 'Idle'})
|
106
|
+
obj['First'] = 'Terry'
|
107
|
+
obj['Last'] = 'Jones'
|
108
|
+
obj['First'].should == 'Terry'
|
109
|
+
obj['Last'].should == 'Jones'
|
110
|
+
end
|
111
|
+
end #[]=
|
112
|
+
|
113
|
+
describe "#modified" do
|
114
|
+
it "BusinessObject with a valid LastModDateTime value" do
|
115
|
+
# Parse the string version of now in order to truncate extra precision
|
116
|
+
# (otherwise the date won't compare equal later)
|
117
|
+
now = DateTime.parse(DateTime.now.to_s)
|
118
|
+
|
119
|
+
obj = MySubclass.create({:last_mod_date_time => now})
|
120
|
+
obj.modified.should == now
|
121
|
+
end
|
122
|
+
|
123
|
+
it "BusinessObject with an invalid LastModDateTime value" do
|
124
|
+
obj = MySubclass.create({:last_mod_date_time => 'bogus'})
|
125
|
+
lambda do
|
126
|
+
obj.modified
|
127
|
+
end.should raise_error(RuntimeError, /Cannot parse LastModDateTime: 'bogus'/)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "BusinessObject without a LastModDateTime field" do
|
131
|
+
xml = %Q{
|
132
|
+
<BusinessObject Name="MySubclass">
|
133
|
+
<FieldList>
|
134
|
+
</FieldList>
|
135
|
+
</BusinessObject>
|
136
|
+
}
|
137
|
+
obj = MySubclass.new(xml)
|
138
|
+
lambda do
|
139
|
+
obj.modified
|
140
|
+
end.should raise_error(RuntimeError, /missing LastModDateTime/)
|
141
|
+
end
|
142
|
+
end #modified
|
143
|
+
|
144
|
+
describe "#mod_s" do
|
145
|
+
it "TODO"
|
146
|
+
end #mod_s
|
147
|
+
|
148
|
+
describe "#newer_than?" do
|
149
|
+
before(:each) do
|
150
|
+
@now = DateTime.now
|
151
|
+
@older = MySubclass.create({:last_mod_date_time => (@now - 1)})
|
152
|
+
@newer = MySubclass.create({:last_mod_date_time => @now})
|
153
|
+
end
|
154
|
+
|
155
|
+
it "true when this one was modified more recently than another" do
|
156
|
+
@newer.newer_than?(@older).should be_true
|
157
|
+
end
|
158
|
+
|
159
|
+
it "false when this one was modified less recently than another" do
|
160
|
+
@older.newer_than?(@newer).should be_false
|
161
|
+
end
|
162
|
+
end #newer_than?
|
163
|
+
|
164
|
+
describe "#to_xml" do
|
165
|
+
it "TODO"
|
166
|
+
end #to_xml
|
167
|
+
|
168
|
+
describe "#get_field_node" do
|
169
|
+
before(:each) do
|
170
|
+
xml = %Q{
|
171
|
+
<BusinessObject Name="MySubclass">
|
172
|
+
<FieldList>
|
173
|
+
<Field Name="First">Eric</Field>
|
174
|
+
<Field Name="Last">Idle</Field>
|
175
|
+
</FieldList>
|
176
|
+
</BusinessObject>
|
177
|
+
}
|
178
|
+
@obj = MySubclass.new(xml)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "returns the Field having the given Name" do
|
182
|
+
first_node = @obj.get_field_node('First')
|
183
|
+
first_node.should be_a(Nokogiri::XML::Node)
|
184
|
+
first_node.attr('Name').should == 'First'
|
185
|
+
first_node.inner_html.should == 'Eric'
|
186
|
+
end
|
187
|
+
|
188
|
+
it "returns nil when a Field with the given Name is not found" do
|
189
|
+
@obj.get_field_node('Bogus').should be_nil
|
190
|
+
end
|
191
|
+
end #get_field_node
|
192
|
+
|
193
|
+
describe "#field_values" do
|
194
|
+
before(:each) do
|
195
|
+
xml = %Q{
|
196
|
+
<BusinessObject Name="MySubclass">
|
197
|
+
<FieldList>
|
198
|
+
<Field Name="First">Eric</Field>
|
199
|
+
<Field Name="Last">Pierce</Field>
|
200
|
+
</FieldList>
|
201
|
+
<Relationship Name="Other fields">
|
202
|
+
<FieldList>
|
203
|
+
<Field Name="Middle">Matthew</Field>
|
204
|
+
</FieldList>
|
205
|
+
</Relationship>
|
206
|
+
</BusinessObject>
|
207
|
+
}
|
208
|
+
@obj = MySubclass.new(xml)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "includes fields inside the main FieldList element only" do
|
212
|
+
@obj.field_values.should include('First')
|
213
|
+
@obj.field_values.should include('Last')
|
214
|
+
@obj.field_values.should_not include('Middle')
|
215
|
+
end
|
216
|
+
|
217
|
+
it "hashes field names to their values" do
|
218
|
+
@obj.field_values['First'].should == 'Eric'
|
219
|
+
@obj.field_values['Last'].should == 'Pierce'
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "#copy_fields_from" do
|
224
|
+
before(:each) do
|
225
|
+
xml = %Q{
|
226
|
+
<BusinessObject Name="MySubclass">
|
227
|
+
<FieldList>
|
228
|
+
<Field Name="Status">Original Status</Field>
|
229
|
+
<Field Name="Description">Original Description</Field>
|
230
|
+
<Field Name="Comment">Original Comment</Field>
|
231
|
+
</FieldList>
|
232
|
+
</BusinessObject>
|
233
|
+
}
|
234
|
+
@obj1 = MySubclass.new(xml)
|
235
|
+
@obj2 = MySubclass.new(xml)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "copies fields from another BusinessObject" do
|
239
|
+
@obj2['Status'] = 'Modified Status'
|
240
|
+
@obj2['Description'] = 'Modified Description'
|
241
|
+
|
242
|
+
@obj1.copy_fields_from(@obj2, 'Status', 'Description')
|
243
|
+
@obj1['Status'].should == 'Modified Status'
|
244
|
+
@obj1['Description'].should == 'Modified Description'
|
245
|
+
@obj1['Comment'].should == 'Original Comment'
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end # Instance methods
|
249
|
+
end # Cherby::BusinessObject
|
250
|
+
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'cherby/cherwell'
|
3
|
+
require 'cherby/exceptions'
|
4
|
+
require 'savon/mock/spec_helper'
|
5
|
+
|
6
|
+
describe Cherby::Cherwell do
|
7
|
+
include Savon::SpecHelper
|
8
|
+
|
9
|
+
before(:all) do
|
10
|
+
savon.mock!
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:all) do
|
14
|
+
savon.unmock!
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
# TODO: Mock this!
|
19
|
+
@config = {
|
20
|
+
'url' => CHERWELL_WSDL,
|
21
|
+
'username' => 'somebody',
|
22
|
+
'password' => 'somepass',
|
23
|
+
}
|
24
|
+
@cherwell = Cherby::Cherwell.new(CHERWELL_WSDL)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#initialize" do
|
28
|
+
it "sets configuration from a hash"
|
29
|
+
it "creates a new Cherby::Client instance" do
|
30
|
+
@cherwell.client.should be_a(Cherby::Client)
|
31
|
+
end
|
32
|
+
end #initialize
|
33
|
+
|
34
|
+
describe "#login" do
|
35
|
+
it "success when Cherwell returns a true status" do
|
36
|
+
login_response = savon_response('Login', 'true')
|
37
|
+
savon.expects(:login).with(:message => :any).
|
38
|
+
returns(login_response)
|
39
|
+
@cherwell.login.should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises Cherby::LoginFailed when client.login raises any exception" do
|
43
|
+
error = "Arbitrary exception message"
|
44
|
+
@cherwell.client.stub(:call).with(:login, :message => anything).
|
45
|
+
and_raise(RuntimeError.new(error))
|
46
|
+
lambda do
|
47
|
+
@cherwell.login
|
48
|
+
end.should raise_error(Cherby::LoginFailed, error)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "raises Cherby::LoginFailed when Cherwell returns a false status" do
|
52
|
+
savon.expects(:login).with(:message => :any).
|
53
|
+
returns(savon_response('Login', 'false'))
|
54
|
+
lambda do
|
55
|
+
@cherwell.login
|
56
|
+
end.should raise_error(
|
57
|
+
Cherby::LoginFailed,
|
58
|
+
/Cherwell returned false status/)
|
59
|
+
end
|
60
|
+
end #login
|
61
|
+
|
62
|
+
describe "#logout" do
|
63
|
+
it "returns true when Cherwell returns a true status" do
|
64
|
+
savon.expects(:logout).with(:message => :any).
|
65
|
+
returns(savon_response('Logout', 'true'))
|
66
|
+
@cherwell.logout.should be_true
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns false when Cherwell returns a false status" do
|
70
|
+
savon.expects(:logout).with(:message => :any).
|
71
|
+
returns(savon_response('Logout', 'false'))
|
72
|
+
@cherwell.logout.should be_false
|
73
|
+
end
|
74
|
+
end #logout
|
75
|
+
|
76
|
+
describe "#incident" do
|
77
|
+
it "returns a Cherby::Incident instance" do
|
78
|
+
incident_id = '51949'
|
79
|
+
incident_xml = File.read(File.join(DATA_DIR, 'incident.xml'))
|
80
|
+
@cherwell.stub(:get_object_xml).
|
81
|
+
with('Incident', incident_id).
|
82
|
+
and_return(incident_xml)
|
83
|
+
@cherwell.incident(incident_id).should be_a(Cherby::Incident)
|
84
|
+
end
|
85
|
+
end #incident
|
86
|
+
|
87
|
+
describe "#task" do
|
88
|
+
it "returns a Cherby::Task instance" do
|
89
|
+
task_id = '12345'
|
90
|
+
task_xml = File.read(File.join(DATA_DIR, 'task.xml'))
|
91
|
+
@cherwell.stub(:get_object_xml).
|
92
|
+
with('Task', task_id).
|
93
|
+
and_return(task_xml)
|
94
|
+
@cherwell.task(task_id).should be_a(Cherby::Task)
|
95
|
+
end
|
96
|
+
end #task
|
97
|
+
|
98
|
+
describe "#get_object_xml" do
|
99
|
+
before(:each) do
|
100
|
+
@name = 'Thing'
|
101
|
+
@rec_id = '12345678901234567890123456789012'
|
102
|
+
@public_id = '12345'
|
103
|
+
@thing_xml = %Q{
|
104
|
+
<FieldList>
|
105
|
+
<Field Name="Name">#{@name}</Field>
|
106
|
+
<Field Name="RecID">#{@rec_id}</Field>
|
107
|
+
</FieldList>
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
it "invokes GetBusinessObject for 32-character RecID" do
|
112
|
+
savon.expects(:get_business_object).with(
|
113
|
+
:message => {
|
114
|
+
:busObNameOrId => @name,
|
115
|
+
:busObRecId => @rec_id,
|
116
|
+
}
|
117
|
+
).returns(
|
118
|
+
savon_response('GetBusinessObject', @thing_xml)
|
119
|
+
)
|
120
|
+
@cherwell.get_object_xml(@name, @rec_id)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "invokes GetBusinessObjectByPublicId for < 32-character IDs" do
|
124
|
+
savon.expects(:get_business_object_by_public_id).with(
|
125
|
+
:message => {
|
126
|
+
:busObNameOrId => @name,
|
127
|
+
:busObPublicId => @public_id,
|
128
|
+
}
|
129
|
+
).returns(
|
130
|
+
savon_response('GetBusinessObjectByPublicId', @thing_xml)
|
131
|
+
)
|
132
|
+
@cherwell.get_object_xml(@name, @public_id)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "returns a raw XML response string" do
|
136
|
+
xml = "<Foo>Bar</Foo>"
|
137
|
+
savon.expects(:get_business_object_by_public_id).with(
|
138
|
+
:message => :any
|
139
|
+
).returns(
|
140
|
+
savon_response('GetBusinessObjectByPublicId', xml)
|
141
|
+
)
|
142
|
+
result = @cherwell.get_object_xml(@name, @public_id)
|
143
|
+
result.should == xml
|
144
|
+
end
|
145
|
+
|
146
|
+
it "raises a Cherby::SoapError if a Savon::Error occurs" do
|
147
|
+
soap_fault = Savon::Error.new("Kaboom")
|
148
|
+
@cherwell.client.stub(:call).and_raise(soap_fault)
|
149
|
+
lambda do
|
150
|
+
@cherwell.get_object_xml(@name, @public_id)
|
151
|
+
end.should raise_error(
|
152
|
+
Cherby::SoapError, /Kaboom/)
|
153
|
+
end
|
154
|
+
end #get_object_xml
|
155
|
+
|
156
|
+
describe "#update_object_xml" do
|
157
|
+
before(:each) do
|
158
|
+
@public_id = '80909'
|
159
|
+
@xml = %Q{
|
160
|
+
<Foo>Bar</Foo>
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
it "invokes UpdateBusinessObjectByPublicId with the given XML" do
|
165
|
+
savon.expects(:update_business_object_by_public_id).with(
|
166
|
+
:message => {
|
167
|
+
:busObNameOrId => 'Incident',
|
168
|
+
:busObPublicId => @public_id,
|
169
|
+
:updateXml => @xml
|
170
|
+
}
|
171
|
+
).returns(
|
172
|
+
savon_response('UpdateBusinessObjectByPublicId', 'true')
|
173
|
+
)
|
174
|
+
@cherwell.stub(:last_error => nil)
|
175
|
+
@cherwell.update_object_xml('Incident', @public_id, @xml)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "returns the #last_error string" do
|
179
|
+
savon.expects(:update_business_object_by_public_id).
|
180
|
+
with(:message => :any).
|
181
|
+
returns(savon_response('UpdateBusinessObjectByPublicId', 'false'))
|
182
|
+
|
183
|
+
error_message = "Failed to update object"
|
184
|
+
@cherwell.stub(:last_error => error_message)
|
185
|
+
result = @cherwell.update_object_xml('Incident', @public_id, @xml)
|
186
|
+
result.should == error_message
|
187
|
+
end
|
188
|
+
end #update_object_xml
|
189
|
+
|
190
|
+
describe "#save_incident" do
|
191
|
+
before(:each) do
|
192
|
+
@public_id = '62521'
|
193
|
+
@incident_data = {
|
194
|
+
:incident_id => @public_id,
|
195
|
+
:service => 'Consulting Services',
|
196
|
+
:sub_category => 'New/Modified Functionality',
|
197
|
+
:priority => '4',
|
198
|
+
}
|
199
|
+
@incident = Cherby::Incident.create(@incident_data)
|
200
|
+
@cherwell.stub(:last_error => nil)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "invokes UpdateBusinessObjectByPublicId with the Incident XML" do
|
204
|
+
savon.expects(:update_business_object_by_public_id).with(
|
205
|
+
:message => {
|
206
|
+
:busObNameOrId => 'Incident',
|
207
|
+
:busObPublicId => @public_id,
|
208
|
+
:updateXml => @incident.to_xml
|
209
|
+
}
|
210
|
+
).returns(
|
211
|
+
savon_response('UpdateBusinessObjectByPublicId', 'true')
|
212
|
+
)
|
213
|
+
@cherwell.save_incident(@incident)
|
214
|
+
end
|
215
|
+
end #save_incident
|
216
|
+
|
217
|
+
describe "#save_task" do
|
218
|
+
before(:each) do
|
219
|
+
@public_id = '90210'
|
220
|
+
@task_data = {
|
221
|
+
:task_id => @public_id,
|
222
|
+
:parent_id => '90000'
|
223
|
+
}
|
224
|
+
@task = Cherby::Task.create(@task_data)
|
225
|
+
@cherwell.stub(:last_error => nil)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "invokes UpdateBusinessObjectByPublicId with the Task XML" do
|
229
|
+
savon.expects(:update_business_object_by_public_id).with(
|
230
|
+
:message => {
|
231
|
+
:busObNameOrId => 'Task',
|
232
|
+
:busObPublicId => @public_id,
|
233
|
+
:updateXml => @task.to_xml
|
234
|
+
}
|
235
|
+
).returns(
|
236
|
+
savon_response('UpdateBusinessObjectByPublicId', 'true')
|
237
|
+
)
|
238
|
+
@cherwell.save_task(@task)
|
239
|
+
end
|
240
|
+
end #save_task
|
241
|
+
|
242
|
+
describe "#create_incident" do
|
243
|
+
before(:each) do
|
244
|
+
@incident_data = {
|
245
|
+
:service => 'Consulting Services',
|
246
|
+
:sub_category => 'New/Modified Functionality',
|
247
|
+
:priority => '4',
|
248
|
+
}
|
249
|
+
@public_id = '54321'
|
250
|
+
end
|
251
|
+
|
252
|
+
it "invokes CreateBusinessObject with incident XML" do
|
253
|
+
savon.expects(:create_business_object).with(
|
254
|
+
:message => {
|
255
|
+
:busObNameOrId => 'Incident',
|
256
|
+
:creationXml => Cherby::Incident.create(@incident_data).to_xml
|
257
|
+
}
|
258
|
+
).returns(
|
259
|
+
savon_response('CreateBusinessObject', @public_id)
|
260
|
+
)
|
261
|
+
@cherwell.create_incident(@incident_data)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "returns a Cherby::Incident instance with IncidentID set" do
|
265
|
+
savon.expects(:create_business_object).with(:message => :any).returns(
|
266
|
+
savon_response('CreateBusinessObject', @public_id)
|
267
|
+
)
|
268
|
+
result = @cherwell.create_incident(@incident_data)
|
269
|
+
result.should be_a(Cherby::Incident)
|
270
|
+
result['IncidentID'].should == @public_id
|
271
|
+
end
|
272
|
+
|
273
|
+
it "returns nil if incident creation failed (Cherwell returned nil)" do
|
274
|
+
savon.expects(:create_business_object).with(:message => :any).returns(
|
275
|
+
savon_response('CreateBusinessObject', nil)
|
276
|
+
)
|
277
|
+
result = @cherwell.create_incident(@incident_data)
|
278
|
+
result.should be_nil
|
279
|
+
end
|
280
|
+
end #create_incident
|
281
|
+
|
282
|
+
describe "#last_error" do
|
283
|
+
it "returns the GetLastError response text" do
|
284
|
+
error_message = "Object reference not set to an instance of an object"
|
285
|
+
savon.expects(:get_last_error).with(:message => {}).returns(
|
286
|
+
savon_response('GetLastError', error_message)
|
287
|
+
)
|
288
|
+
@cherwell.last_error.should == error_message
|
289
|
+
end
|
290
|
+
|
291
|
+
it "returns nil if GetLastError returns nil" do
|
292
|
+
savon.expects(:get_last_error).with(:message => {}).returns(
|
293
|
+
savon_response('GetLastError', nil)
|
294
|
+
)
|
295
|
+
@cherwell.last_error.should be_nil
|
296
|
+
end
|
297
|
+
end #last_error
|
298
|
+
|
299
|
+
end # describe Cherby::Cherwell
|
300
|
+
|