ruby-trello 2.0.0 → 2.3.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 (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