ruby-trello 2.0.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +106 -17
  3. data/lib/trello.rb +47 -34
  4. data/lib/trello/action.rb +10 -8
  5. data/lib/trello/association_builder/has_many.rb +17 -0
  6. data/lib/trello/association_builder/has_one.rb +16 -0
  7. data/lib/trello/association_fetcher/has_many.rb +26 -0
  8. data/lib/trello/association_fetcher/has_many/fetch.rb +47 -0
  9. data/lib/trello/association_fetcher/has_many/params.rb +56 -0
  10. data/lib/trello/association_fetcher/has_one.rb +25 -0
  11. data/lib/trello/association_fetcher/has_one/fetch.rb +49 -0
  12. data/lib/trello/association_fetcher/has_one/params.rb +36 -0
  13. data/lib/trello/association_infer_tool.rb +13 -0
  14. data/lib/trello/association_proxy.rb +1 -1
  15. data/lib/trello/attachment.rb +13 -10
  16. data/lib/trello/basic_data.rb +16 -49
  17. data/lib/trello/board.rb +17 -3
  18. data/lib/trello/card.rb +103 -38
  19. data/lib/trello/checklist.rb +14 -13
  20. data/lib/trello/client.rb +1 -1
  21. data/lib/trello/comment.rb +4 -4
  22. data/lib/trello/custom_field.rb +131 -0
  23. data/lib/trello/custom_field_item.rb +98 -0
  24. data/lib/trello/custom_field_option.rb +22 -0
  25. data/lib/trello/error.rb +12 -0
  26. data/lib/trello/item.rb +7 -7
  27. data/lib/trello/item_state.rb +3 -3
  28. data/lib/trello/label.rb +30 -12
  29. data/lib/trello/label_name.rb +10 -10
  30. data/lib/trello/list.rb +6 -6
  31. data/lib/trello/member.rb +10 -9
  32. data/lib/trello/notification.rb +6 -6
  33. data/lib/trello/organization.rb +11 -11
  34. data/lib/trello/plugin_datum.rb +6 -6
  35. data/lib/trello/register_attributes.rb +54 -0
  36. data/lib/trello/token.rb +6 -5
  37. data/lib/trello/webhook.rb +5 -5
  38. data/spec/action_spec.rb +22 -1
  39. data/spec/basic_data_spec.rb +58 -0
  40. data/spec/board_spec.rb +28 -2
  41. data/spec/card_spec.rb +183 -8
  42. data/spec/cassettes/can_add_a_file_from_url_on_a_card.yml +189 -0
  43. data/spec/cassettes/can_add_a_file_on_a_card.yml +200 -0
  44. data/spec/cassettes/can_add_a_member_to_a_card.yml +190 -0
  45. data/spec/cassettes/can_add_label_on_a_card.yml +281 -0
  46. data/spec/cassettes/can_close_bong_a_card.yml +189 -0
  47. data/spec/cassettes/can_get_actions.yml +196 -0
  48. data/spec/cassettes/can_get_attachments.yml +187 -0
  49. data/spec/cassettes/can_get_comments.yml +193 -0
  50. data/spec/cassettes/can_move_a_card_to_another_board_with_specific_list.yml +373 -0
  51. data/spec/cassettes/can_move_a_card_to_another_board_without_specific_list.yml +281 -0
  52. data/spec/cassettes/can_move_a_card_to_another_list.yml +281 -0
  53. data/spec/cassettes/can_remove_a_member_from_a_card.yml +185 -0
  54. data/spec/cassettes/can_remove_an_attachment_on_a_card.yml +277 -0
  55. data/spec/cassettes/can_remove_an_upvote_on_a_card.yml +465 -0
  56. data/spec/cassettes/can_remove_label_on_a_card.yml +279 -0
  57. data/spec/cassettes/can_success_add_comment_to_a_card.yml +196 -0
  58. data/spec/cassettes/can_success_copy_checklist_to_a_card.yml +281 -0
  59. data/spec/cassettes/can_success_copy_checklist_to_a_card_without_name_pos.yml +281 -0
  60. data/spec/cassettes/can_success_create_a_card.yml +99 -0
  61. data/spec/cassettes/can_success_create_new_checklist_to_a_card.yml +189 -0
  62. data/spec/cassettes/can_success_delete_card.yml +185 -0
  63. data/spec/cassettes/can_success_upate_a_card.yml +189 -0
  64. data/spec/cassettes/can_success_update_bong_a_board.yml +283 -0
  65. data/spec/cassettes/can_success_update_bong_a_card.yml +191 -0
  66. data/spec/cassettes/can_upvote_on_a_card.yml +469 -0
  67. data/spec/cassettes/card_find_with_id_and_get_all_fields.yml +95 -0
  68. data/spec/cassettes/card_find_with_id_and_get_specific_fields.yml +96 -0
  69. data/spec/cassettes/custom_field_item_save_1.yml +97 -0
  70. data/spec/cassettes/custom_field_item_save_2.yml +281 -0
  71. data/spec/cassettes/get_board_of_card.yml +187 -0
  72. data/spec/cassettes/get_check_item_states_of_card.yml +188 -0
  73. data/spec/cassettes/get_checklists_of_card.yml +187 -0
  74. data/spec/cassettes/get_cover_image_of_card.yml +187 -0
  75. data/spec/cassettes/get_custom_field_items_of_card.yml +187 -0
  76. data/spec/cassettes/get_list_of_card.yml +188 -0
  77. data/spec/cassettes/get_lists.yml +187 -0
  78. data/spec/cassettes/get_members_of_card.yml +189 -0
  79. data/spec/cassettes/get_plugin_data_of_card.yml +187 -0
  80. data/spec/cassettes/get_voters_of_card.yml +188 -0
  81. data/spec/cassettes/remove_upvote_on_a_card_when_have_not_voted.yml +366 -0
  82. data/spec/cassettes/revote_on_a_card.yml +464 -0
  83. data/spec/checklist_spec.rb +39 -3
  84. data/spec/client_spec.rb +5 -1
  85. data/spec/custom_field_item_spec.rb +192 -0
  86. data/spec/custom_field_option_spec.rb +49 -0
  87. data/spec/custom_field_spec.rb +261 -0
  88. data/spec/integration/basic_data/many_spec.rb +123 -0
  89. data/spec/integration/basic_data/one_spec.rb +84 -0
  90. data/spec/integration/basic_data/register_attributes_spec.rb +75 -0
  91. data/spec/integration/board/update!_spec.rb +31 -0
  92. data/spec/integration/board_lists_spec.rb +21 -0
  93. data/spec/integration/card/add_and_remove_attachment_spec.rb +45 -0
  94. data/spec/integration/card/add_and_remove_label_spec.rb +35 -0
  95. data/spec/integration/card/add_checklist_spec.rb +32 -0
  96. data/spec/integration/card/add_comment_spec.rb +19 -0
  97. data/spec/integration/card/add_memeber_spec.rb +19 -0
  98. data/spec/integration/card/associations/actions_spec.rb +17 -0
  99. data/spec/integration/card/associations/attachments_spec.rb +18 -0
  100. data/spec/integration/card/associations/board_spec.rb +17 -0
  101. data/spec/integration/card/associations/check_item_states_spec.rb +17 -0
  102. data/spec/integration/card/associations/checklists_spec.rb +18 -0
  103. data/spec/integration/card/associations/comments_spec.rb +19 -0
  104. data/spec/integration/card/associations/cover_image_spec.rb +18 -0
  105. data/spec/integration/card/associations/custom_field_items_spec.rb +18 -0
  106. data/spec/integration/card/associations/list_spec.rb +16 -0
  107. data/spec/integration/card/associations/members_spec.rb +18 -0
  108. data/spec/integration/card/associations/plugin_data_spec.rb +18 -0
  109. data/spec/integration/card/associations/voters_spec.rb +17 -0
  110. data/spec/integration/card/close!_spec.rb +16 -0
  111. data/spec/integration/card/create_new_check_list_spec.rb +19 -0
  112. data/spec/integration/card/create_spec.rb +50 -0
  113. data/spec/integration/card/delete_spec.rb +16 -0
  114. data/spec/integration/card/find_spec.rb +67 -0
  115. data/spec/integration/card/move_to_board_spec.rb +36 -0
  116. data/spec/integration/card/move_to_list_spec.rb +20 -0
  117. data/spec/integration/card/remove_member_spec.rb +19 -0
  118. data/spec/integration/card/save_spec.rb +61 -0
  119. data/spec/integration/card/update!_spec.rb +53 -0
  120. data/spec/integration/card/vote_spec.rb +50 -0
  121. data/spec/integration/custom_field_item_spec.rb +47 -0
  122. data/spec/item_spec.rb +20 -0
  123. data/spec/label_spec.rb +99 -0
  124. data/spec/list_spec.rb +21 -0
  125. data/spec/member_spec.rb +23 -0
  126. data/spec/notification_spec.rb +21 -0
  127. data/spec/organization_spec.rb +26 -0
  128. data/spec/spec_helper.rb +96 -23
  129. data/spec/token_spec.rb +19 -0
  130. data/spec/unit/trello/association_builder/has_many_spec.rb +36 -0
  131. data/spec/unit/trello/association_builder/has_one_spec.rb +36 -0
  132. data/spec/unit/trello/association_fetcher/has_many/fetch_spec.rb +38 -0
  133. data/spec/unit/trello/association_fetcher/has_many/params_spec.rb +107 -0
  134. data/spec/unit/trello/association_fetcher/has_many_spec.rb +50 -0
  135. data/spec/unit/trello/association_fetcher/has_one/fetch_spec.rb +51 -0
  136. data/spec/unit/trello/association_fetcher/has_one/params_spec.rb +81 -0
  137. data/spec/unit/trello/association_fetcher/has_one_spec.rb +49 -0
  138. data/spec/unit/trello/association_infer_tool_spec.rb +41 -0
  139. data/spec/unit/trello/basic_data_spec.rb +54 -0
  140. data/spec/unit/trello/card_spec.rb +103 -0
  141. data/spec/webhook_spec.rb +20 -0
  142. metadata +224 -30
@@ -9,16 +9,16 @@ module Trello
9
9
  # Supply a hash of stringkeyed data retrieved from the Trello API representing
10
10
  # a label.
11
11
  def update_fields(fields)
12
- attributes[:yellow] = fields['yellow']
13
- attributes[:red] = fields['red']
14
- attributes[:orange] = fields['orange']
15
- attributes[:green] = fields['green']
16
- attributes[:purple] = fields['purple']
17
- attributes[:blue] = fields['blue']
18
- attributes[:sky] = fields['sky']
19
- attributes[:pink] = fields['pink']
20
- attributes[:lime] = fields['lime']
21
- attributes[:black] = fields['black']
12
+ attributes[:yellow] = fields['yellow'] || attributes[:yellow]
13
+ attributes[:red] = fields['red'] || attributes[:red]
14
+ attributes[:orange] = fields['orange'] || attributes[:orange]
15
+ attributes[:green] = fields['green'] || attributes[:green]
16
+ attributes[:purple] = fields['purple'] || attributes[:purple]
17
+ attributes[:blue] = fields['blue'] || attributes[:blue]
18
+ attributes[:sky] = fields['sky'] || attributes[:sky]
19
+ attributes[:pink] = fields['pink'] || attributes[:pink]
20
+ attributes[:lime] = fields['lime'] || attributes[:lime]
21
+ attributes[:black] = fields['black'] || attributes[:black]
22
22
 
23
23
  self
24
24
  end
@@ -41,12 +41,12 @@ module Trello
41
41
  # Supply a hash of string keyed data retrieved from the Trello API representing
42
42
  # a List.
43
43
  def update_fields(fields)
44
- attributes[:id] = fields['id']
45
- attributes[:name] = fields['name'] || fields[:name]
46
- attributes[:closed] = fields['closed']
47
- attributes[:board_id] = fields['idBoard'] || fields[:board_id]
48
- attributes[:pos] = fields['pos'] || fields[:pos]
49
- attributes[:source_list_id] = fields['idListSource'] || fields[:source_list_id]
44
+ attributes[:id] = fields['id'] || attributes[:id]
45
+ attributes[:name] = fields['name'] || fields[:name] || attributes[:name]
46
+ attributes[:closed] = fields['closed'] if fields.has_key?('closed')
47
+ attributes[:board_id] = fields['idBoard'] || fields[:board_id] || attributes[:board_id]
48
+ attributes[:pos] = fields['pos'] || fields[:pos] || attributes[:pos]
49
+ attributes[:source_list_id] = fields['idListSource'] || fields[:source_list_id] || attributes[:source_list_id]
50
50
  self
51
51
  end
52
52
 
@@ -39,14 +39,14 @@ module Trello
39
39
  # Supply a hash of string keyed data retrieved from the Trello API representing
40
40
  # an Member.
41
41
  def update_fields(fields)
42
- attributes[:id] = fields['id']
43
- attributes[:full_name] = fields['fullName']
44
- attributes[:email] = fields['email']
45
- attributes[:username] = fields['username']
46
- attributes[:initials] = fields['initials']
47
- attributes[:avatar_id] = fields['avatarHash']
48
- attributes[:bio] = fields['bio']
49
- attributes[:url] = fields['url']
42
+ attributes[:id] = fields['id'] || attributes[:id]
43
+ attributes[:full_name] = fields['fullName'] || attributes[:full_name]
44
+ attributes[:email] = fields['email'] || attributes[:email]
45
+ attributes[:username] = fields['username'] || attributes[:username]
46
+ attributes[:initials] = fields['initials'] || attributes[:initials]
47
+ attributes[:avatar_id] = fields['avatarHash'] || attributes[:avatar_id]
48
+ attributes[:bio] = fields['bio'] || attributes[:bio]
49
+ attributes[:url] = fields['url'] || attributes[:url]
50
50
  self
51
51
  end
52
52
 
@@ -92,7 +92,8 @@ module Trello
92
92
 
93
93
  def save
94
94
  @previously_changed = changes
95
- @changed_attributes.clear
95
+ @changed_attributes.clear if @changed_attributes.respond_to?(:clear)
96
+ changes_applied if respond_to?(:changes_applied)
96
97
 
97
98
  return update! if id
98
99
  end
@@ -25,12 +25,12 @@ module Trello
25
25
  end
26
26
 
27
27
  def update_fields(fields)
28
- attributes[:id] = fields['id']
29
- attributes[:unread] = fields['unread']
30
- attributes[:type] = fields['type']
31
- attributes[:date] = fields['date']
32
- attributes[:data] = fields['data']
33
- attributes[:member_creator_id] = fields['idMemberCreator']
28
+ attributes[:id] = fields['id'] || attributes[:id]
29
+ attributes[:unread] = fields['unread'] if fields.has_key?('unread')
30
+ attributes[:type] = fields['type'] || attributes[:type]
31
+ attributes[:date] = fields['date'] || attributes[:date]
32
+ attributes[:data] = fields['data'] || attributes[:data]
33
+ attributes[:member_creator_id] = fields['idMemberCreator'] || attributes[:member_creator_id]
34
34
  self
35
35
  end
36
36
 
@@ -34,17 +34,17 @@ module Trello
34
34
  # Supply a hash of string keyed data retrieved from the Trello API representing
35
35
  # an Organization.
36
36
  def update_fields(fields)
37
- attributes[:id] = fields['id']
38
- attributes[:name] = fields['name']
39
- attributes[:display_name] = fields['displayName']
40
- attributes[:description] = fields['desc']
41
- attributes[:url] = fields['url']
42
- attributes[:invited] = fields['invited']
43
- attributes[:website] = fields['website']
44
- attributes[:logo_hash] = fields['logoHash']
45
- attributes[:billable_member_count] = fields['billableMemberCount']
46
- attributes[:active_billable_member_count] = fields['activeBillableMemberCount']
47
- attributes[:memberships] = fields['memberships']
37
+ attributes[:id] = fields['id'] || attributes[:id]
38
+ attributes[:name] = fields['name'] || attributes[:name]
39
+ attributes[:display_name] = fields['displayName'] || attributes[:display_name]
40
+ attributes[:description] = fields['desc'] || attributes[:description]
41
+ attributes[:url] = fields['url'] || attributes[:url]
42
+ attributes[:invited] = fields['invited'] if fields.has_key?('invited')
43
+ attributes[:website] = fields['website'] || attributes[:website]
44
+ attributes[:logo_hash] = fields['logoHash'] || attributes[:logo_hash]
45
+ attributes[:billable_member_count] = fields['billableMemberCount'] || attributes[:billable_member_count]
46
+ attributes[:active_billable_member_count] = fields['activeBillableMemberCount'] || attributes[:active_billable_member_count]
47
+ attributes[:memberships] = fields['memberships'] || attributes[:memberships]
48
48
  self
49
49
  end
50
50
 
@@ -21,12 +21,12 @@ module Trello
21
21
  # Supply a hash of stringkeyed data retrieved from the Trello API representing
22
22
  # an attachment.
23
23
  def update_fields(fields)
24
- attributes[:id] = fields['id']
25
- attributes[:idPlugin] = fields['idPlugin']
26
- attributes[:scope] = fields['scope']
27
- attributes[:value] = JSON.parse fields['value']
28
- attributes[:idModel] = fields['idModel']
29
- attributes[:access] = fields['access']
24
+ attributes[:id] = fields['id'] || attributes[:id]
25
+ attributes[:idPlugin] = fields['idPlugin'] || attributes[:idPlugin]
26
+ attributes[:scope] = fields['scope'] || attributes[:scope]
27
+ attributes[:value] = JSON.parse(fields['value']).presence if fields.has_key?('value')
28
+ attributes[:idModel] = fields['idModel'] || attributes[:idModel]
29
+ attributes[:access] = fields['access'] || attributes[:access]
30
30
  self
31
31
  end
32
32
  end
@@ -0,0 +1,54 @@
1
+ module Trello
2
+ class RegisterAttributes
3
+ class << self
4
+ def execute(model_klass, names, readonly_names)
5
+ names ||= []
6
+ readonly_names ||= []
7
+
8
+ define_method_attributes(model_klass, names)
9
+ define_getters(model_klass, names)
10
+ define_setters(model_klass, names, readonly_names)
11
+ track_attributes_changes(model_klass, names)
12
+ end
13
+
14
+ private
15
+
16
+ def define_method_attributes(model_klass, names)
17
+ model_klass.class_eval do
18
+ define_method :attributes do
19
+ @__attributes ||= names.reduce({}) do |attrs, name|
20
+ attrs.merge(name.to_sym => nil)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def define_getters(model_klass, names)
27
+ model_klass.class_eval do
28
+ names.each do |key|
29
+ define_method(key) { @__attributes[key] }
30
+ end
31
+ end
32
+ end
33
+
34
+ def define_setters(model_klass, names, readonly_names)
35
+ model_klass.class_eval do
36
+ names.each do |key|
37
+ next if readonly_names.include?(key.to_sym)
38
+
39
+ define_method("#{key}=") do |value|
40
+ send("#{key}_will_change!") if value != @__attributes[key]
41
+ @__attributes[key] = value
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def track_attributes_changes(model_klass, names)
48
+ model_klass.class_eval do
49
+ define_attribute_methods(names)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -23,11 +23,12 @@ module Trello
23
23
 
24
24
  # :nodoc:
25
25
  def update_fields(fields)
26
- attributes[:id] = fields['id']
27
- attributes[:member_id] = fields['idMember']
28
- attributes[:created_at] = Time.iso8601(fields['dateCreated'])
29
- attributes[:permissions] = fields['permissions'] || {}
30
- attributes[:webhooks] = fields['webhooks']
26
+ attributes[:id] = fields['id'] || attributes[:id]
27
+ attributes[:member_id] = fields['idMember'] || attributes[:member_id]
28
+ attributes[:created_at] = Time.iso8601(fields['dateCreated']) rescue nil if fields.has_key?('dateCreated')
29
+ attributes[:permissions] = fields['permissions'] || attributes[:permissions]
30
+ attributes[:permissions] ||= {}
31
+ attributes[:webhooks] = fields['webhooks'] || attributes[:webhooks]
31
32
  end
32
33
 
33
34
  # Returns a reference to the user who authorized the token.
@@ -48,11 +48,11 @@ module Trello
48
48
 
49
49
  # @return [Trello::Webhook] self
50
50
  def update_fields(fields)
51
- attributes[:id] = fields['id']
52
- attributes[:description] = fields['description'] || fields[:description]
53
- attributes[:id_model] = fields['idModel'] || fields[:id_model]
54
- attributes[:callback_url] = fields['callbackURL'] || fields[:callback_url]
55
- attributes[:active] = fields['active']
51
+ attributes[:id] = fields['id'] || attributes[:id]
52
+ attributes[:description] = fields['description'] || fields[:description] || attributes[:description]
53
+ attributes[:id_model] = fields['idModel'] || fields[:id_model] || attributes[:id_model]
54
+ attributes[:callback_url] = fields['callbackURL'] || fields[:callback_url] || attributes[:callback_url]
55
+ attributes[:active] = fields['active'] if fields.has_key?('active')
56
56
  self
57
57
  end
58
58
 
@@ -116,7 +116,7 @@ module Trello
116
116
  before do
117
117
  allow(client)
118
118
  .to receive(:get)
119
- .with('/members/abcdef123456789123456789', {})
119
+ .with('/actions/4ee2482134a81a757a08af47/memberCreator')
120
120
  .and_return user_payload
121
121
  end
122
122
 
@@ -124,5 +124,26 @@ module Trello
124
124
  expect(action.member_creator).to_not be_nil
125
125
  end
126
126
  end
127
+
128
+ describe "#update_fields" do
129
+ it "does not set any fields when the fields argument is empty" do
130
+ expected = {
131
+ 'id' => 'id',
132
+ 'type' => 'type',
133
+ 'data' => 'data',
134
+ 'idMemberCreator' => 'member_creator_id',
135
+ 'member' => 'member_participant'
136
+ }
137
+
138
+ action = Action.new(expected)
139
+ action.client = client
140
+
141
+ action.update_fields({})
142
+
143
+ expected.each do |key, value|
144
+ expect(action.send(value)).to eq expected[key]
145
+ end
146
+ end
147
+ end
127
148
  end
128
149
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ describe BasicData do
5
+ describe "equality" do
6
+ specify "two objects of the same type are equal if their id values are equal" do
7
+ data_object = Card.new('id' => 'abc123')
8
+ other_data_object = Card.new('id' => 'abc123')
9
+
10
+ expect(data_object).to eq(other_data_object)
11
+ end
12
+
13
+ specify "two object of the samy type are not equal if their id values are different" do
14
+ data_object = Card.new('id' => 'abc123')
15
+ other_data_object = Card.new('id' => 'def456')
16
+
17
+ expect(data_object).not_to eq(other_data_object)
18
+ end
19
+
20
+ specify "two object of different types are not equal even if their id values are equal" do
21
+ card = Card.new('id' => 'abc123')
22
+ list = List.new('id' => 'abc123')
23
+
24
+ expect(card.id).to eq(list.id)
25
+ expect(card).to_not eq(list)
26
+ end
27
+ end
28
+
29
+ describe "hash equality" do
30
+ specify "two objects of the same type point to the same hash key" do
31
+ data_object = Card.new('id' => 'abc123')
32
+ other_data_object = Card.new('id' => 'abc123')
33
+
34
+ hash = {data_object => 'one'}
35
+
36
+ expect(hash[other_data_object]).to eq('one')
37
+ end
38
+
39
+ specify "two object of the same type with different ids do not point to the same hash key" do
40
+ data_object = Card.new('id' => 'abc123')
41
+ other_data_object = Card.new('id' => 'def456')
42
+
43
+ hash = {data_object => 'one'}
44
+
45
+ expect(hash[other_data_object]).to be_nil
46
+ end
47
+
48
+ specify "two object of different types with same ids do not point to the same hash key" do
49
+ card = Card.new('id' => 'abc123')
50
+ list = List.new('id' => 'abc123')
51
+
52
+ hash = {card => 'one'}
53
+
54
+ expect(hash[list]).to be_nil
55
+ end
56
+ end
57
+ end
58
+ end
@@ -225,6 +225,19 @@ module Trello
225
225
  end
226
226
  end
227
227
 
228
+ context "checklists" do
229
+ before do
230
+ allow(client)
231
+ .to receive(:get)
232
+ .with("/boards/abcdef123456789123456789/checklists", {filter: :all})
233
+ .and_return checklists_payload
234
+ end
235
+
236
+ it "has a list of checklists" do
237
+ expect(board.checklists.count).to be > 0
238
+ end
239
+ end
240
+
228
241
  context "organization" do
229
242
  before do
230
243
  allow(client)
@@ -238,6 +251,19 @@ module Trello
238
251
  end
239
252
  end
240
253
 
254
+ context "custom fields" do
255
+ before do
256
+ allow(client)
257
+ .to receive(:get)
258
+ .with("/boards/abcdef123456789123456789/customFields", {})
259
+ .and_return JSON.generate([custom_fields_details.first])
260
+ end
261
+
262
+ it "has custom fields" do
263
+ expect(board.custom_fields.count).to be > 0
264
+ end
265
+ end
266
+
241
267
  it "is not closed" do
242
268
  expect(board).not_to be_closed
243
269
  end
@@ -317,7 +343,7 @@ module Trello
317
343
  end
318
344
 
319
345
  it "puts all fields except id" do
320
- expected_fields = %w{ name description closed starred idOrganization}.map { |s| s.to_sym }
346
+ expected_fields = %w{ name desc closed starred idOrganization}.map { |s| s.to_sym }
321
347
 
322
348
  expect(client).to receive(:put) do |anything, body|
323
349
  expect(body.keys).to match expected_fields
@@ -369,7 +395,7 @@ module Trello
369
395
  .to receive(:put)
370
396
  .with("/boards/#{board.id}/", {
371
397
  name: "new name",
372
- description: "new description",
398
+ desc: "new description",
373
399
  closed: true,
374
400
  starred: true,
375
401
  idOrganization: nil })
@@ -187,6 +187,7 @@ module Trello
187
187
  .to receive(:put)
188
188
  .once
189
189
  .with("/cards/abcdef123456789123456789", payload)
190
+ .and_return(payload.to_json)
190
191
 
191
192
  card.name = expected_new_name
192
193
  card.save
@@ -199,7 +200,10 @@ module Trello
199
200
  desc: expected_new_desc,
200
201
  }
201
202
 
202
- expect(client).to receive(:put).once.with("/cards/abcdef123456789123456789", payload)
203
+ expect(client)
204
+ .to receive(:put).once
205
+ .with("/cards/abcdef123456789123456789", payload)
206
+ .and_return(payload.to_json)
203
207
 
204
208
  card.desc = expected_new_desc
205
209
  card.save
@@ -257,7 +261,6 @@ module Trello
257
261
  expect(card.pos).to_not be_nil
258
262
  end
259
263
 
260
-
261
264
  it 'gets its creation time' do
262
265
  expect(card.created_at).to be_kind_of Time
263
266
  end
@@ -308,7 +311,7 @@ module Trello
308
311
  before do
309
312
  allow(client)
310
313
  .to receive(:get)
311
- .with("/attachments/abcdef123456789123456789", {})
314
+ .with("/cards/#{card.id}/attachments/abcdef123456789123456789", {})
312
315
  .and_return JSON.generate(attachments_details.first)
313
316
  end
314
317
 
@@ -338,6 +341,41 @@ module Trello
338
341
  end
339
342
  end
340
343
 
344
+ context "custom field items" do
345
+ before do
346
+ allow(client)
347
+ .to receive(:get)
348
+ .with("/cards/abcdef123456789123456789/customFieldItems", {})
349
+ .and_return JSON.generate([custom_field_item_details])
350
+ end
351
+
352
+ it "has a list of custom field items" do
353
+ expect(card.custom_field_items.count).to be > 0
354
+ end
355
+
356
+ it "clears the custom field value on a card" do
357
+ params = { value: {} }
358
+
359
+ expect(client)
360
+ .to receive(:put)
361
+ .with("/card/abcdef123456789123456789/customField/abcdef123456789123456789/item", params)
362
+
363
+ card.custom_field_items.last.remove
364
+ end
365
+
366
+ it "updates a custom field value" do
367
+ payload = { value: { text: 'Test Text' } }
368
+
369
+ expect(client)
370
+ .to receive(:put)
371
+ .with("/card/abcdef123456789123456789/customField/abcdef123456789123456789/item", payload)
372
+
373
+ text_custom_field = card.custom_field_items.last
374
+ text_custom_field.value = { text: 'Test Text' }
375
+ text_custom_field.save
376
+ end
377
+ end
378
+
341
379
  context "list" do
342
380
  before do
343
381
  allow(client)
@@ -345,6 +383,7 @@ module Trello
345
383
  .with("/lists/abcdef123456789123456789", {})
346
384
  .and_return JSON.generate(lists_details.first)
347
385
  end
386
+
348
387
  it 'has a list' do
349
388
  expect(card.list).to_not be_nil
350
389
  end
@@ -399,7 +438,46 @@ module Trello
399
438
  card.move_to_board(other_board, other_list)
400
439
  end
401
440
 
402
- it 'should not be moved if new board is identical with old board', focus: true do
441
+ it 'can be moved to a list on the same board' do
442
+ current_board = double(id: 'abcdef123456789123456789')
443
+ other_list = double(
444
+ id: '987654321987654321fedcba',
445
+ board_id: 'abcdef123456789123456789'
446
+ )
447
+ allow(List).to receive(:find).with('987654321987654321fedcba').
448
+ and_return(other_list)
449
+ allow(card).to receive(:board).and_return(current_board)
450
+ payload = {value: other_list.id}
451
+
452
+ expect(client)
453
+ .to receive(:put)
454
+ .with('/cards/abcdef123456789123456789/idList', payload)
455
+
456
+ card.move_to_list_on_any_board(other_list.id)
457
+ end
458
+
459
+ it 'can be moved to a list on another board' do
460
+ current_board = double(id: 'abcdef123456789123456789')
461
+ other_board = double(id: '987654321987654321fedcba')
462
+ other_list = double(
463
+ id: '987654321987654321aalist',
464
+ board_id: '987654321987654321fedcba'
465
+ )
466
+ allow(List).to receive(:find).with('987654321987654321aalist').
467
+ and_return(other_list)
468
+ allow(card).to receive(:board).and_return(current_board)
469
+ allow(Board).to receive(:find).with('987654321987654321fedcba').
470
+ and_return(other_board)
471
+ payload = { value: other_board.id, idList: other_list.id }
472
+
473
+ expect(client)
474
+ .to receive(:put)
475
+ .with('/cards/abcdef123456789123456789/idBoard', payload)
476
+
477
+ card.move_to_list_on_any_board(other_list.id)
478
+ end
479
+
480
+ it 'should not be moved if new board is identical with old board' do
403
481
  other_board = double(id: 'abcdef123456789123456789')
404
482
  expect(client).to_not receive(:put)
405
483
  card.move_to_board(other_board)
@@ -415,7 +493,7 @@ module Trello
415
493
 
416
494
  allow(client)
417
495
  .to receive(:get)
418
- .with("/members/abcdef123456789123456789")
496
+ .with("/cards/abcdef123456789123456789/members")
419
497
  .and_return user_payload
420
498
  end
421
499
 
@@ -432,7 +510,7 @@ module Trello
432
510
 
433
511
  expect(client)
434
512
  .to receive(:post)
435
- .with("/cards/abcdef123456789123456789/members", payload)
513
+ .with("/cards/abcdef123456789123456789/idMembers", payload)
436
514
 
437
515
  card.add_member(new_member)
438
516
  end
@@ -442,7 +520,7 @@ module Trello
442
520
 
443
521
  expect(client)
444
522
  .to receive(:delete)
445
- .with("/cards/abcdef123456789123456789/members/#{existing_member.id}")
523
+ .with("/cards/abcdef123456789123456789/idMembers/#{existing_member.id}")
446
524
 
447
525
  card.remove_member(existing_member)
448
526
  end
@@ -517,7 +595,6 @@ module Trello
517
595
  end
518
596
  end
519
597
 
520
-
521
598
  context "comments" do
522
599
  it "posts a comment" do
523
600
  expect(client)
@@ -715,6 +792,7 @@ module Trello
715
792
  .to receive(:put)
716
793
  .once
717
794
  .with("/cards/abcdef123456789123456789", payload)
795
+ .and_return(payload.to_json)
718
796
 
719
797
  card.close!
720
798
  end
@@ -732,6 +810,7 @@ module Trello
732
810
  .to receive(:put)
733
811
  .once
734
812
  .with("/cards/abcdef123456789123456789", payload)
813
+ .and_return(payload.to_json)
735
814
 
736
815
  card.due = due_date
737
816
  card.save
@@ -746,6 +825,7 @@ module Trello
746
825
  .to receive(:put)
747
826
  .once
748
827
  .with("/cards/abcdef123456789123456789", payload)
828
+ .and_return(payload.to_json)
749
829
 
750
830
  card.due_complete = true
751
831
  card.save
@@ -753,5 +833,100 @@ module Trello
753
833
  expect(card.due_complete).to be true
754
834
  end
755
835
  end
836
+
837
+ describe '#update_fields' do
838
+ context 'when the fields argument is empty' do
839
+ let(:fields) { {} }
840
+
841
+ it 'card does not set any fields' do
842
+ expected = cards_details.first
843
+
844
+ card = Card.new(expected)
845
+ card.client = client
846
+
847
+ card.update_fields(fields)
848
+
849
+ expected.each do |key, value|
850
+ if card.respond_to?(key) && key != 'labels'
851
+ expect(card.send(key)).to eq value
852
+ end
853
+
854
+ expect(card.labels).to eq expected['labels'].map { |lbl| Trello::Label.new(lbl) }
855
+ expect(card.short_id).to eq expected['idShort']
856
+ expect(card.short_url).to eq expected['shortUrl']
857
+ expect(card.board_id).to eq expected['idBoard']
858
+ expect(card.member_ids).to eq expected['idMembers']
859
+ expect(card.cover_image_id).to eq expected['idAttachmentCover']
860
+ expect(card.list_id).to eq expected['idList']
861
+ expect(card.card_labels).to eq expected['idLabels']
862
+ end
863
+ end
864
+ end
865
+
866
+ context 'when the fields argument has at least one field' do
867
+ let(:expected) { cards_details.first }
868
+ let(:card) {
869
+ card = Card.new(expected)
870
+ card.client = client
871
+ card
872
+ }
873
+
874
+ context 'and the field does changed' do
875
+ let(:fields) { { desc: 'Awesome things have changed.' } }
876
+
877
+ it 'card does set the changed fields' do
878
+ card.update_fields(fields)
879
+
880
+ expect(card.desc).to eq('Awesome things have changed.')
881
+ end
882
+
883
+ it 'card has been mark as changed' do
884
+ card.update_fields(fields)
885
+
886
+ expect(card.changed?).to be_truthy
887
+ end
888
+ end
889
+
890
+ context "and the field doesn't changed" do
891
+ let(:fields) { { desc: expected[:desc] } }
892
+
893
+ it "card attributes doesn't changed" do
894
+ card.update_fields(fields)
895
+
896
+ expect(card.desc).to eq(expected['desc'])
897
+ end
898
+
899
+ it "card hasn't been mark as changed", pending: true do
900
+ card.update_fields(fields)
901
+
902
+ expect(card.changed?).to be_falsy
903
+ end
904
+ end
905
+
906
+ context "and the field isn't a correct attributes of the card" do
907
+ let(:fields) { { abc: 'abc' } }
908
+
909
+ it "card attributes doesn't changed" do
910
+ card.update_fields(fields)
911
+
912
+ expect(card.labels).to eq expected['labels'].map { |lbl| Trello::Label.new(lbl) }
913
+ expect(card.short_id).to eq expected['idShort']
914
+ expect(card.short_url).to eq expected['shortUrl']
915
+ expect(card.board_id).to eq expected['idBoard']
916
+ expect(card.member_ids).to eq expected['idMembers']
917
+ expect(card.cover_image_id).to eq expected['idAttachmentCover']
918
+ expect(card.list_id).to eq expected['idList']
919
+ expect(card.card_labels).to eq expected['idLabels']
920
+ expect(card.desc).to eq expected['desc']
921
+ end
922
+
923
+ it "card hasn't been mark as changed" do
924
+ card.update_fields(fields)
925
+
926
+ expect(card.changed?).to be_falsy
927
+ end
928
+ end
929
+ end
930
+ end
756
931
  end
757
932
  end