mavenlink 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +3 -0
  6. data/README.md +241 -0
  7. data/Rakefile +28 -0
  8. data/bin/mavenlink-console +18 -0
  9. data/doc/ml_logo_lb-primary.png +0 -0
  10. data/lib/config/specification.yml +1665 -0
  11. data/lib/mavenlink.rb +134 -0
  12. data/lib/mavenlink/account_invitation.rb +4 -0
  13. data/lib/mavenlink/account_membership.rb +4 -0
  14. data/lib/mavenlink/additional_item.rb +4 -0
  15. data/lib/mavenlink/assignment.rb +5 -0
  16. data/lib/mavenlink/attachment.rb +11 -0
  17. data/lib/mavenlink/backup_approver_association.rb +4 -0
  18. data/lib/mavenlink/client.rb +116 -0
  19. data/lib/mavenlink/concerns/custom_fieldable.rb +9 -0
  20. data/lib/mavenlink/concerns/indestructible.rb +11 -0
  21. data/lib/mavenlink/concerns/locked_record.rb +30 -0
  22. data/lib/mavenlink/cost_rate.rb +4 -0
  23. data/lib/mavenlink/custom_field.rb +4 -0
  24. data/lib/mavenlink/custom_field_choice.rb +5 -0
  25. data/lib/mavenlink/custom_field_value.rb +4 -0
  26. data/lib/mavenlink/errors.rb +47 -0
  27. data/lib/mavenlink/expense.rb +4 -0
  28. data/lib/mavenlink/expense_category.rb +4 -0
  29. data/lib/mavenlink/expense_report_submission.rb +7 -0
  30. data/lib/mavenlink/external_payment.rb +4 -0
  31. data/lib/mavenlink/external_reference.rb +24 -0
  32. data/lib/mavenlink/fixed_fee_item.rb +4 -0
  33. data/lib/mavenlink/holiday.rb +4 -0
  34. data/lib/mavenlink/holiday_calendar.rb +4 -0
  35. data/lib/mavenlink/holiday_calendar_association.rb +4 -0
  36. data/lib/mavenlink/holiday_calendar_membership.rb +4 -0
  37. data/lib/mavenlink/invoice.rb +4 -0
  38. data/lib/mavenlink/logger.rb +62 -0
  39. data/lib/mavenlink/model.rb +279 -0
  40. data/lib/mavenlink/organization.rb +4 -0
  41. data/lib/mavenlink/organization_membership.rb +4 -0
  42. data/lib/mavenlink/participation.rb +4 -0
  43. data/lib/mavenlink/post.rb +4 -0
  44. data/lib/mavenlink/project_template.rb +4 -0
  45. data/lib/mavenlink/project_template_assignment.rb +4 -0
  46. data/lib/mavenlink/railtie.rb +7 -0
  47. data/lib/mavenlink/rate_card.rb +4 -0
  48. data/lib/mavenlink/rate_card_role.rb +4 -0
  49. data/lib/mavenlink/rate_card_set.rb +4 -0
  50. data/lib/mavenlink/rate_card_set_version.rb +30 -0
  51. data/lib/mavenlink/rate_card_version.rb +4 -0
  52. data/lib/mavenlink/request.rb +241 -0
  53. data/lib/mavenlink/resolution.rb +4 -0
  54. data/lib/mavenlink/response.rb +22 -0
  55. data/lib/mavenlink/role.rb +5 -0
  56. data/lib/mavenlink/settings.rb +11 -0
  57. data/lib/mavenlink/skill.rb +4 -0
  58. data/lib/mavenlink/skill_category.rb +4 -0
  59. data/lib/mavenlink/skill_membership.rb +4 -0
  60. data/lib/mavenlink/specificators/association.rb +13 -0
  61. data/lib/mavenlink/specificators/attribute.rb +13 -0
  62. data/lib/mavenlink/specificators/base.rb +24 -0
  63. data/lib/mavenlink/specificators/validation.rb +27 -0
  64. data/lib/mavenlink/status_report.rb +4 -0
  65. data/lib/mavenlink/story.rb +8 -0
  66. data/lib/mavenlink/story_allocation_day.rb +5 -0
  67. data/lib/mavenlink/story_dependency.rb +5 -0
  68. data/lib/mavenlink/story_task.rb +5 -0
  69. data/lib/mavenlink/tag.rb +5 -0
  70. data/lib/mavenlink/time_adjustment.rb +4 -0
  71. data/lib/mavenlink/time_entry.rb +4 -0
  72. data/lib/mavenlink/time_off_entry.rb +4 -0
  73. data/lib/mavenlink/timesheet_submission.rb +4 -0
  74. data/lib/mavenlink/user.rb +5 -0
  75. data/lib/mavenlink/vendor.rb +4 -0
  76. data/lib/mavenlink/workspace.rb +21 -0
  77. data/lib/mavenlink/workspace_group.rb +5 -0
  78. data/lib/mavenlink/workspace_invoice_preference.rb +4 -0
  79. data/lib/mavenlink/workweek.rb +4 -0
  80. data/lib/mavenlink/workweek_membership.rb +4 -0
  81. data/mavenlink.gemspec +29 -0
  82. data/spec/lib/mavenlink/account_membership_spec.rb +8 -0
  83. data/spec/lib/mavenlink/assignment_spec.rb +17 -0
  84. data/spec/lib/mavenlink/attachment_spec.rb +30 -0
  85. data/spec/lib/mavenlink/backup_approver_association_spec.rb +9 -0
  86. data/spec/lib/mavenlink/client_spec.rb +187 -0
  87. data/spec/lib/mavenlink/concerns/indestructible_spec.rb +13 -0
  88. data/spec/lib/mavenlink/concerns/locked_record_spec.rb +28 -0
  89. data/spec/lib/mavenlink/cost_rate_spec.rb +9 -0
  90. data/spec/lib/mavenlink/custom_field_value_spec.rb +10 -0
  91. data/spec/lib/mavenlink/expense_report_submission_spec.rb +16 -0
  92. data/spec/lib/mavenlink/expense_spec.rb +23 -0
  93. data/spec/lib/mavenlink/external_references_spec.rb +144 -0
  94. data/spec/lib/mavenlink/holiday_calendar_association_spec.rb +8 -0
  95. data/spec/lib/mavenlink/holiday_calendar_membership_spec.rb +8 -0
  96. data/spec/lib/mavenlink/holiday_spec.rb +7 -0
  97. data/spec/lib/mavenlink/invalid_request_error_spec.rb +9 -0
  98. data/spec/lib/mavenlink/invoice_spec.rb +176 -0
  99. data/spec/lib/mavenlink/model_spec.rb +439 -0
  100. data/spec/lib/mavenlink/post_spec.rb +23 -0
  101. data/spec/lib/mavenlink/rate_card_set_version_spec.rb +119 -0
  102. data/spec/lib/mavenlink/record_invalid_error_spec.rb +16 -0
  103. data/spec/lib/mavenlink/record_not_found_error_spec.rb +9 -0
  104. data/spec/lib/mavenlink/request_spec.rb +381 -0
  105. data/spec/lib/mavenlink/response_spec.rb +50 -0
  106. data/spec/lib/mavenlink/role_spec.rb +9 -0
  107. data/spec/lib/mavenlink/settings_spec.rb +23 -0
  108. data/spec/lib/mavenlink/skill_category_spec.rb +7 -0
  109. data/spec/lib/mavenlink/skill_membership_spec.rb +9 -0
  110. data/spec/lib/mavenlink/skill_spec.rb +8 -0
  111. data/spec/lib/mavenlink/specificators/association_spec.rb +25 -0
  112. data/spec/lib/mavenlink/specificators/attribute_spec.rb +25 -0
  113. data/spec/lib/mavenlink/specificators/validation_spec.rb +39 -0
  114. data/spec/lib/mavenlink/story_allocation_day_spec.rb +64 -0
  115. data/spec/lib/mavenlink/story_dependency_spec.rb +16 -0
  116. data/spec/lib/mavenlink/story_spec.rb +69 -0
  117. data/spec/lib/mavenlink/time_adjustment_spec.rb +13 -0
  118. data/spec/lib/mavenlink/time_entry_spec.rb +43 -0
  119. data/spec/lib/mavenlink/time_off_entry_spec.rb +9 -0
  120. data/spec/lib/mavenlink/user_spec.rb +138 -0
  121. data/spec/lib/mavenlink/workspace_group_spec.rb +25 -0
  122. data/spec/lib/mavenlink/workspace_spec.rb +431 -0
  123. data/spec/lib/mavenlink_spec.rb +43 -0
  124. data/spec/spec_helper.rb +31 -0
  125. data/spec/support/shared_examples.rb +148 -0
  126. metadata +267 -0
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mavenlink::WorkspaceGroup, stub_requests: true do
4
+ it_should_behave_like 'model', 'workspace_groups'
5
+
6
+ describe 'validations' do
7
+ it { should validate_presence_of :name }
8
+ it { should ensure_inclusion_of(:company).in_array([true, false]) }
9
+ it { should_not allow_value('true').for(:company) }
10
+ it { should_not allow_value('false').for(:company) }
11
+ it { should_not allow_value(nil).for(:company) }
12
+ end
13
+
14
+ describe 'associations' do
15
+ it { should respond_to :workspaces }
16
+ it { should respond_to :external_references }
17
+ end
18
+
19
+ describe 'attributes' do
20
+ it { should respond_to :name }
21
+ it { should respond_to :company }
22
+ it { should respond_to :add_workspace_ids }
23
+ it { should respond_to :remove_workspace_ids }
24
+ end
25
+ end
@@ -0,0 +1,431 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mavenlink::Workspace, stub_requests: true do
4
+ let(:model) { described_class }
5
+
6
+ it { should be_a Mavenlink::Model }
7
+ it { should be_a Mavenlink::Concerns::Indestructible }
8
+
9
+ describe "associations" do
10
+ it { should respond_to :external_references }
11
+ it { should respond_to :approver }
12
+ end
13
+
14
+ let(:response) {
15
+ {
16
+ 'count' => 1,
17
+ 'results' => [{'key' => 'workspaces', 'id' => '7'}],
18
+ 'workspaces' => {
19
+ '7' => {'title' => 'My new project', 'id' => '7'}
20
+ }
21
+ }
22
+ }
23
+
24
+ let(:updated_response) {
25
+ {
26
+ 'count' => 1,
27
+ 'results' => [{'key' => 'workspaces', 'id' => '7'}],
28
+ 'workspaces' => {
29
+ '7' => {'title' => 'Updated project', 'id' => '7'}
30
+ }
31
+ }
32
+ }
33
+
34
+ before do
35
+ stub_request :get, '/api/v1/workspaces?only=7', response
36
+ stub_request :get, '/api/v1/workspaces?only=8', {'count' => 0, 'results' => []}
37
+ stub_request :post, '/api/v1/workspaces', response
38
+ stub_request :put, '/api/v1/workspaces/7', updated_response
39
+ stub_request :delete, '/api/v1/workspaces/4', {'count' => 0, 'results' => []} # TODO: replace with real one
40
+ end
41
+
42
+ describe 'association calls' do
43
+ let(:record) { described_class.find(7) }
44
+ let(:response) {
45
+ {
46
+ 'count' => 1,
47
+ 'results' => [{'key' => 'workspaces', 'id' => '7'}, {'key' => 'users', 'id' => '2'}],
48
+ 'users' => {
49
+ '2' => {
50
+ 'id' => 2,
51
+ 'full_name' => 'John Doe'
52
+ }
53
+ },
54
+ 'workspaces' => {
55
+ '7' => {
56
+ 'title' => 'My new project', 'id' => '7',
57
+ 'participant_ids' => ['2'],
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ specify do
64
+ expect(record.participants.count).to eq(1)
65
+ end
66
+
67
+ specify do
68
+ expect(record.participants.first).to be_a(Mavenlink::User)
69
+ end
70
+
71
+ it 'saves the client scope' do
72
+ expect(record.participants.first.client).to eq(record.client)
73
+ end
74
+ end
75
+
76
+ describe 'validations' do
77
+ context 'new record' do
78
+ it { should be_a_new_record }
79
+ it { should validate_presence_of :title }
80
+ end
81
+
82
+ context 'persisted record' do
83
+ subject { described_class.new(id: 12) }
84
+ it { should be_persisted }
85
+ it { should validate_presence_of :title }
86
+ it { should_not ensure_inclusion_of(:creator_role).in_array(%w[maven buyer]) }
87
+ it { should allow_value(nil).for(:creator_role) }
88
+ end
89
+ end
90
+
91
+ describe 'instance methods' do
92
+ subject { model.new(title: 'Some title', creator_role: 'maven') }
93
+
94
+ specify do
95
+ expect(subject.scoped_im).to be_a Mavenlink::Request
96
+ end
97
+ end
98
+
99
+ describe 'class methods' do
100
+ subject { model }
101
+ its(:collection_name) { should == 'workspaces' }
102
+
103
+ describe '.scoped' do
104
+ subject { model.scoped }
105
+
106
+ it { should be_a Mavenlink::Request }
107
+ its(:collection_name) { should == 'workspaces' }
108
+ end
109
+
110
+ describe '.find' do
111
+ specify do
112
+ expect(model.find(7)).to be_a model
113
+ end
114
+
115
+ specify do
116
+ expect(model.find(7).id).to eq('7')
117
+ end
118
+
119
+ specify do
120
+ expect(model.find(8)).to be_nil
121
+ end
122
+ end
123
+
124
+ describe '.create' do
125
+ context 'valid record' do
126
+ specify do
127
+ expect(model.create(title: 'Some title', creator_role: 'maven')).to be_a model
128
+ end
129
+
130
+ specify do
131
+ expect(model.create(title: 'Some title', creator_role: 'maven')).to be_valid
132
+ end
133
+
134
+ specify do
135
+ expect(model.create(title: 'Some title', creator_role: 'maven')).to be_persisted
136
+ end
137
+ end
138
+
139
+ context 'invalid record' do
140
+ specify do
141
+ expect(model.create(title: '', creator_role: '')).to be_a model
142
+ end
143
+
144
+ specify do
145
+ expect(model.create(title: '', creator_role: '')).not_to be_valid
146
+ end
147
+
148
+ specify do
149
+ expect(model.create(title: '', creator_role: '')).to be_a_new_record
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '.create!' do
155
+ context 'valid record' do
156
+ specify do
157
+ expect { model.create!(title: 'Some title', creator_role: 'maven') }.not_to raise_error
158
+ end
159
+ end
160
+
161
+ context 'invalid record' do
162
+ specify do
163
+ expect { model.create!(title: '', creator_role: '') }.to raise_error Mavenlink::RecordInvalidError, /Title.*blank/
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '.models' do
169
+ specify do
170
+ expect(model.models).to be_empty
171
+ end
172
+
173
+ specify do
174
+ expect(Mavenlink::Model.models).to include({'workspaces' => Mavenlink::Workspace})
175
+ end
176
+ end
177
+
178
+ describe '.specification' do
179
+ specify do
180
+ expect(model.specification).to be_a Hash
181
+ end
182
+
183
+ specify do
184
+ expect(model.specification).not_to be_empty
185
+ end
186
+ end
187
+
188
+ describe '.attributes' do
189
+ specify do
190
+ expect(model.attributes).to be_an Array
191
+ end
192
+
193
+ specify do
194
+ expect(model.attributes).not_to be_empty
195
+ end
196
+ end
197
+
198
+ describe '.available_attributes' do
199
+ specify do
200
+ expect(model.available_attributes).to be_an Array
201
+ end
202
+
203
+ specify do
204
+ expect(model.available_attributes).not_to be_empty
205
+ end
206
+ end
207
+
208
+ describe '.create_attributes' do
209
+ specify do
210
+ expect(model.create_attributes).to be_an Array
211
+ end
212
+
213
+ specify do
214
+ expect(model.create_attributes).not_to be_empty
215
+ end
216
+ end
217
+
218
+ describe '.update_attributes' do
219
+ specify do
220
+ expect(model.update_attributes).to be_an Array
221
+ end
222
+
223
+ specify do
224
+ expect(model.update_attributes).not_to be_empty
225
+ end
226
+ end
227
+
228
+ describe '.wrap' do
229
+ specify do
230
+ expect(model.wrap(nil)).to be_a_new_record
231
+ end
232
+
233
+ context 'existing record' do
234
+ let(:brainstem_record) do
235
+ BrainstemAdaptor::Record.new('workspaces', '7', Mavenlink::Response.new(response))
236
+ end
237
+
238
+ specify do
239
+ expect(model.wrap(brainstem_record)).not_to be_a_new_record
240
+ end
241
+
242
+ specify do
243
+ expect(model.wrap(brainstem_record)).to be_a Mavenlink::Workspace
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ describe '#initialize' do
250
+ it 'accepts attributes' do
251
+ expect(model.new(any_custom_key: 'value set')).to include(any_custom_key: 'value set')
252
+ end
253
+
254
+ end
255
+
256
+ describe '#persisted?' do
257
+ specify do
258
+ expect(model.new).not_to be_persisted
259
+ end
260
+
261
+ specify do
262
+ expect(model.new(id: 1)).to be_persisted
263
+ end
264
+ end
265
+
266
+ describe '#new_record?' do
267
+ specify do
268
+ expect(model.new).to be_new_record
269
+ end
270
+
271
+ specify do
272
+ expect(model.new(id: 1)).not_to be_new_record
273
+ end
274
+ end
275
+
276
+ describe '#save' do
277
+ context 'valid record' do
278
+ context 'new record' do
279
+ subject { model.new(title: 'Some title', creator_role: 'maven') }
280
+
281
+ specify do
282
+ expect(subject.save).to eq(true)
283
+ end
284
+
285
+ specify do
286
+ expect { subject.save }.to change(subject, :persisted?).from(false).to(true)
287
+ end
288
+
289
+ it 'reloads record fields taking it from response' do
290
+ expect { subject.save }.to change { subject.title }.from('Some title').to('My new project')
291
+ end
292
+ end
293
+
294
+ context 'persisted record' do
295
+ subject { model.create(title: 'Some title', creator_role: 'maven') }
296
+
297
+ it { should be_persisted }
298
+
299
+ specify do
300
+ expect(subject.save).to eq(true)
301
+ end
302
+
303
+ specify do
304
+ expect { subject.save }.not_to change(subject, :persisted?)
305
+ end
306
+
307
+ it 'reloads record fields taking it from response' do
308
+ expect { subject.save }.to change { subject.title }.from('My new project').to('Updated project')
309
+ end
310
+ end
311
+ end
312
+
313
+ context 'invalid record' do
314
+ context 'new record' do
315
+ subject { model.new(title: '', creator_role: '') }
316
+
317
+ specify do
318
+ expect(subject.save).to eq(false)
319
+ end
320
+
321
+ specify do
322
+ expect { subject.save }.not_to change(subject, :persisted?)
323
+ end
324
+
325
+ it 'does not perform any requests' do
326
+ expect { subject.save }.not_to change { subject.title }
327
+ end
328
+ end
329
+
330
+ context 'persisted record' do
331
+ subject { model.create(title: 'Some title', creator_role: 'maven') }
332
+ before { subject.title = '' }
333
+
334
+ it { should be_persisted }
335
+
336
+ specify do
337
+ expect(subject.save).to eq(false)
338
+ end
339
+
340
+ specify do
341
+ expect { subject.save }.not_to change(subject, :persisted?)
342
+ end
343
+
344
+ it 'does not change anything' do
345
+ expect { subject.save }.not_to change { subject.title }
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ describe '#save!' do
352
+ context 'valid record' do
353
+ context 'new record' do
354
+ subject { model.new(title: 'Some title', creator_role: 'maven') }
355
+
356
+ specify do
357
+ expect(subject.save!).to eq(true)
358
+ end
359
+
360
+ specify do
361
+ expect { subject.save! }.to change(subject, :persisted?).from(false).to(true)
362
+ end
363
+
364
+ it 'reloads record fields taking it from response' do
365
+ expect { subject.save! }.to change { subject.title }.from('Some title').to('My new project')
366
+ end
367
+ end
368
+
369
+ context 'persisted record' do
370
+ subject { model.create(title: 'Some title', creator_role: 'maven') }
371
+
372
+ it { should be_persisted }
373
+
374
+ specify do
375
+ expect(subject.save!).to eq(true)
376
+ end
377
+
378
+ specify do
379
+ expect { subject.save! }.not_to change(subject, :persisted?)
380
+ end
381
+
382
+ it 'reloads record fields taking it from response' do
383
+ expect { subject.save! }.to change { subject.title }.from('My new project').to('Updated project')
384
+ end
385
+ end
386
+ end
387
+
388
+ context 'invalid record' do
389
+ context 'new record' do
390
+ subject { model.new(title: '', creator_role: '') }
391
+
392
+ specify do
393
+ expect { subject.save! }.to raise_error Mavenlink::RecordInvalidError, /Title.*blank/
394
+ end
395
+
396
+ specify do
397
+ expect { subject.save! rescue nil }.not_to change(subject, :persisted?)
398
+ end
399
+
400
+ it 'does not perform any requests' do
401
+ expect { subject.save! rescue nil }.not_to change { subject.title }
402
+ end
403
+ end
404
+
405
+ context 'persisted record' do
406
+ subject { model.create(title: 'Some title', creator_role: 'maven') }
407
+ before { subject.title = '' }
408
+
409
+ it { should be_persisted }
410
+
411
+ specify do
412
+ expect { subject.save! }.to raise_error Mavenlink::RecordInvalidError, /Title.*blank/
413
+ end
414
+
415
+ specify do
416
+ expect { subject.save! rescue nil }.not_to change(subject, :persisted?)
417
+ end
418
+
419
+ it 'does not change anything' do
420
+ expect { subject.save! rescue nil }.not_to change { subject.title }
421
+ end
422
+ end
423
+ end
424
+ end
425
+
426
+ describe '#destroy' do
427
+ specify do
428
+ expect { model.new(id: '4').destroy }.to raise_error Mavenlink::RecordLockedError, /locked.*deleted/
429
+ end
430
+ end
431
+ end