mavenlink 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.
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