cherby 0.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.
- 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
|
+
|