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