ruby-trello-czuger 2.0.0

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +182 -0
  3. data/lib/trello.rb +163 -0
  4. data/lib/trello/action.rb +68 -0
  5. data/lib/trello/association.rb +14 -0
  6. data/lib/trello/association_proxy.rb +42 -0
  7. data/lib/trello/attachment.rb +40 -0
  8. data/lib/trello/authorization.rb +187 -0
  9. data/lib/trello/basic_data.rb +132 -0
  10. data/lib/trello/board.rb +211 -0
  11. data/lib/trello/card.rb +467 -0
  12. data/lib/trello/checklist.rb +143 -0
  13. data/lib/trello/client.rb +120 -0
  14. data/lib/trello/comment.rb +62 -0
  15. data/lib/trello/configuration.rb +68 -0
  16. data/lib/trello/core_ext/array.rb +6 -0
  17. data/lib/trello/core_ext/hash.rb +6 -0
  18. data/lib/trello/core_ext/string.rb +6 -0
  19. data/lib/trello/cover_image.rb +8 -0
  20. data/lib/trello/has_actions.rb +9 -0
  21. data/lib/trello/item.rb +37 -0
  22. data/lib/trello/item_state.rb +30 -0
  23. data/lib/trello/json_utils.rb +64 -0
  24. data/lib/trello/label.rb +108 -0
  25. data/lib/trello/label_name.rb +31 -0
  26. data/lib/trello/list.rb +114 -0
  27. data/lib/trello/member.rb +112 -0
  28. data/lib/trello/multi_association.rb +12 -0
  29. data/lib/trello/net.rb +39 -0
  30. data/lib/trello/notification.rb +61 -0
  31. data/lib/trello/organization.rb +68 -0
  32. data/lib/trello/plugin_datum.rb +34 -0
  33. data/lib/trello/token.rb +37 -0
  34. data/lib/trello/webhook.rb +103 -0
  35. data/spec/action_spec.rb +149 -0
  36. data/spec/array_spec.rb +13 -0
  37. data/spec/association_spec.rb +26 -0
  38. data/spec/basic_auth_policy_spec.rb +51 -0
  39. data/spec/board_spec.rb +442 -0
  40. data/spec/card_spec.rb +822 -0
  41. data/spec/checklist_spec.rb +296 -0
  42. data/spec/client_spec.rb +257 -0
  43. data/spec/configuration_spec.rb +95 -0
  44. data/spec/hash_spec.rb +15 -0
  45. data/spec/integration/how_to_authorize_spec.rb +53 -0
  46. data/spec/integration/how_to_use_boards_spec.rb +48 -0
  47. data/spec/integration/integration_test.rb +40 -0
  48. data/spec/item_spec.rb +75 -0
  49. data/spec/json_utils_spec.rb +73 -0
  50. data/spec/label_spec.rb +205 -0
  51. data/spec/list_spec.rb +253 -0
  52. data/spec/member_spec.rb +159 -0
  53. data/spec/notification_spec.rb +143 -0
  54. data/spec/oauth_policy_spec.rb +160 -0
  55. data/spec/organization_spec.rb +71 -0
  56. data/spec/spec_helper.rb +435 -0
  57. data/spec/string_spec.rb +55 -0
  58. data/spec/token_spec.rb +89 -0
  59. data/spec/trello_spec.rb +134 -0
  60. data/spec/webhook_spec.rb +130 -0
  61. metadata +200 -0
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Trello::Configuration do
4
+ let(:configuration) { Trello::Configuration.new }
5
+
6
+ [
7
+ :consumer_key,
8
+ :consumer_secret,
9
+ :oauth_token,
10
+ :oauth_token_secret,
11
+ :developer_public_key,
12
+ :member_token,
13
+ :return_url
14
+
15
+ ].each do |attribute|
16
+ it "has a #{attribute} attribute" do
17
+ configuration.public_send(:"#{attribute}=", attribute)
18
+ expect(configuration.public_send(attribute)).to eq attribute
19
+ end
20
+ end
21
+
22
+ it 'has a callback (for oauth)' do
23
+ callback = -> { 'foobar' }
24
+ configuration.callback = callback
25
+ expect(configuration.callback.call).to eq('foobar')
26
+ end
27
+
28
+ describe 'initialize' do
29
+ it 'sets key attributes provided as a hash' do
30
+ configuration = Trello::Configuration.new(
31
+ consumer_key: 'consumer_key',
32
+ consumer_secret: 'consumer_secret',
33
+ oauth_token: 'oauth_token',
34
+ oauth_token_secret: 'oauth_token_secret'
35
+ )
36
+ expect(configuration.consumer_key).to eq('consumer_key')
37
+ expect(configuration.consumer_secret).to eq('consumer_secret')
38
+ expect(configuration.oauth_token).to eq('oauth_token')
39
+ expect(configuration.oauth_token_secret).to eq('oauth_token_secret')
40
+ end
41
+ end
42
+
43
+ describe '#credentials' do
44
+ let(:configuration) { Trello::Configuration.new(attributes) }
45
+
46
+ it 'returns an empty if no attributes specified' do
47
+ expect(Trello::Configuration.new({}).credentials).to eq({})
48
+ end
49
+
50
+ it 'returns an empty if attributes incomplete' do
51
+ expect(Trello::Configuration.new(consumer_key: 'consumer_key').credentials).to eq({})
52
+ end
53
+
54
+ it 'returns a hash of oauth attributes' do
55
+ configuration = Trello::Configuration.new(
56
+ consumer_key: 'consumer_key',
57
+ consumer_secret: 'consumer_secret',
58
+ oauth_token: 'oauth_token',
59
+ oauth_token_secret: 'oauth_token_secret'
60
+ )
61
+ expect(configuration.credentials).to eq(
62
+ consumer_key: 'consumer_key',
63
+ consumer_secret: 'consumer_secret',
64
+ oauth_token: 'oauth_token',
65
+ oauth_token_secret: 'oauth_token_secret'
66
+ )
67
+ end
68
+
69
+ it 'includes callback and return url if given' do
70
+ configuration = Trello::Configuration.new(
71
+ consumer_key: 'consumer_key',
72
+ consumer_secret: 'consumer_secret',
73
+ return_url: 'http://example.com',
74
+ callback: 'callback'
75
+ )
76
+ expect(configuration.credentials).to eq(
77
+ consumer_key: 'consumer_key',
78
+ consumer_secret: 'consumer_secret',
79
+ return_url: 'http://example.com',
80
+ callback: 'callback'
81
+ )
82
+ end
83
+
84
+ it 'returns a hash of basic auth policy attributes' do
85
+ configuration = Trello::Configuration.new(
86
+ developer_public_key: 'developer_public_key',
87
+ member_token: 'member_token'
88
+ )
89
+ expect(configuration.credentials).to eq(
90
+ developer_public_key: 'developer_public_key',
91
+ member_token: 'member_token'
92
+ )
93
+ end
94
+ end
95
+ end
data/spec/hash_spec.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'trello/core_ext/hash'
3
+
4
+ describe Hash, '#jsoned_into' do
5
+ include Helpers
6
+
7
+ it "should convert a single parsed json into card" do
8
+ expect(Trello::Card)
9
+ .to receive(:new)
10
+ .once
11
+ .with(cards_details.first)
12
+
13
+ cards_details.first.jsoned_into(Trello::Card)
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ require 'integration/integration_test'
3
+
4
+ describe "Authorizing read-only requests", broken: true do
5
+ include IntegrationTest
6
+
7
+ it "Reading public resources requires just a developer public key" do
8
+ uri = Addressable::URI.parse("https://api.trello.com/1/boards/4ed7e27fe6abb2517a21383d")
9
+ uri.query_values = {
10
+ key: @developer_public_key
11
+ }
12
+
13
+ get(uri).code.should === 200
14
+ end
15
+
16
+ it "Reading private resources requires developer public key AND a member token" do
17
+ uri = Addressable::URI.parse("https://api.trello.com/1/boards/#{@welcome_board}")
18
+ uri.query_values = {
19
+ key: @developer_public_key,
20
+ token: @member_token
21
+ }
22
+
23
+ get(uri).code.should === 200
24
+ end
25
+
26
+ it "can fetch the welcome board" do
27
+ BasicAuthPolicy.developer_public_key = @developer_public_key
28
+ BasicAuthPolicy.member_token = @member_token
29
+
30
+ Container.set Trello::Authorization, "AuthPolicy", BasicAuthPolicy
31
+
32
+ welcome_board = Board.find @welcome_board
33
+ welcome_board.name.should === "Welcome Board"
34
+ welcome_board.id.should === @welcome_board
35
+ end
36
+ end
37
+
38
+ describe "OAuth", broken: true do
39
+ include IntegrationTest
40
+
41
+ before do
42
+ Container.set Trello::Authorization, "AuthPolicy", OAuthPolicy
43
+ end
44
+
45
+ it "[!] actually does not enforce signature at all, only the keys are required" do
46
+ OAuthPolicy.consumer_credential = OAuthCredential.new @developer_public_key, nil
47
+ OAuthPolicy.token = OAuthCredential.new @access_token_key, nil
48
+
49
+ pending "I would expect this to fail because I have signed with nil secrets" do
50
+ -> { Client.get("/boards/#{@welcome_board}/") }.should raise_error
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'integration/integration_test'
3
+
4
+ describe "how to use boards", broken: true do
5
+ include IntegrationTest
6
+
7
+ context "given a valid access token" do
8
+ before :all do
9
+ OAuthPolicy.consumer_credential = OAuthCredential.new @developer_public_key, @developer_secret
10
+ OAuthPolicy.token = OAuthCredential.new @access_token_key, @access_token_secret
11
+ Container.set Trello::Authorization, "AuthPolicy", OAuthPolicy
12
+ end
13
+
14
+ after do
15
+ if @new_board and false == @new_board.closed?
16
+ @new_board.update_fields 'closed' => true
17
+ @new_board.save
18
+ end
19
+ end
20
+
21
+ it "can add a board" do
22
+ @new_board = Board.create(name: "An example")
23
+ @new_board.should_not be_nil
24
+ @new_board.id.should_not be_nil
25
+ @new_board.name.should == "An example"
26
+ @new_board.should_not be_closed
27
+ end
28
+
29
+ it "can read the welcome board" do
30
+ welcome_board = Board.find @welcome_board
31
+ welcome_board.name.should === "Welcome Board"
32
+ welcome_board.id.should === @welcome_board
33
+ end
34
+
35
+ it "can close a board" do
36
+ @new_board = Board.create(name: "[#{Time.now}, CLOSED] An example")
37
+
38
+ @new_board.update_fields 'closed' => true
39
+ @new_board.save
40
+
41
+ Board.find(@new_board.id).should be_closed
42
+ end
43
+
44
+ it "can list all boards" do
45
+ Board.from_response(Client.get("/members/me/boards/")).should be_an Array
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ module IntegrationTest
2
+ include Trello
3
+ include Trello::Authorization
4
+
5
+ class Container
6
+ class << self
7
+ def set(parent, name, value)
8
+ parent.send :remove_const, name
9
+ parent.const_set name, value
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.included(klass)
15
+ klass.class_eval do
16
+ before :all do
17
+ # Getting developer/member key
18
+ # 1. https://trello.com/1/appKey/generate
19
+ # 2. https://trello.com/1/authorize?key=<public_key_here>&name=RubyTrelloIntegrationTests&response_type=token
20
+ # See: https://trello.com/board/trello-public-api/4ed7e27fe6abb2517a21383d
21
+
22
+ @developer_public_key = ENV["DEVELOPER_PUBLIC_KEY"]
23
+ @developer_secret = ENV["DEVELOPER_SECRET"]
24
+ @member_token = ENV["MEMBER_TOKEN"]
25
+ @welcome_board = ENV["WELCOME_BOARD"]
26
+ @access_token_key = ENV["ACCESS_TOKEN_KEY"]
27
+ @access_token_secret = ENV["ACCESS_TOKEN_SECRET"]
28
+
29
+ WebMock.disable!
30
+ end
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def get(uri)
37
+ require "rest_client"
38
+ RestClient.get uri.to_s
39
+ end
40
+ end
data/spec/item_spec.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ describe Item do
5
+ let(:details) {
6
+ {
7
+ 'id' => 'abcdef123456789123456789',
8
+ 'name' => 'test item',
9
+ 'type' => 'check',
10
+ 'state' => 'complete',
11
+ 'pos' => 0
12
+ }
13
+ }
14
+
15
+ let(:item) { Item.new(details) }
16
+
17
+ it 'gets its id' do
18
+ expect(item.id).to eq details['id']
19
+ end
20
+
21
+ it 'gets its name' do
22
+ expect(item.name).to eq details['name']
23
+ end
24
+
25
+ it 'knows its type' do
26
+ expect(item.type).to eq details['type']
27
+ end
28
+
29
+ it 'knows its state' do
30
+ expect(item.state).to eq details['state']
31
+ end
32
+
33
+ it 'knows its pos' do
34
+ expect(item.pos).to eq details['pos']
35
+ end
36
+
37
+ describe '#complete?' do
38
+ before do
39
+ allow(item)
40
+ .to receive(:state)
41
+ .and_return state
42
+ end
43
+
44
+ context 'when complete' do
45
+ let(:state) { 'complete' }
46
+ it { expect(item).to be_complete }
47
+ end
48
+
49
+ context 'when complete' do
50
+ let(:state) { 'incomplete' }
51
+ it { expect(item).not_to be_complete }
52
+ end
53
+ end
54
+
55
+ describe "#update_fields" do
56
+ it "does not set any fields when the fields argument is empty" do
57
+ expected = {
58
+ 'id' => 'id',
59
+ 'name' => 'name',
60
+ 'type' => 'type',
61
+ 'state' => 'state',
62
+ 'pos' => 'pos'
63
+ }
64
+
65
+ item = Item.new(expected)
66
+
67
+ item.update_fields({})
68
+
69
+ expected.each do |key, value|
70
+ expect(item.send(value)).to eq expected[key]
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ RSpec.describe JsonUtils do
5
+ include Helpers
6
+
7
+ describe ".from_json" do
8
+ describe "Trello::Card" do
9
+ it "should convert an array of parsed json into cards" do
10
+ cards = Trello::Card.from_json(cards_details)
11
+
12
+ expect(cards.size).to eq(cards_details.size)
13
+
14
+ card = cards.first
15
+ expect(card).to be_a(Trello::Card)
16
+ expect(card.name).to eq(cards_details.first['name'])
17
+ end
18
+
19
+ it "should convert a single parsed json into card" do
20
+ card_details = cards_details.first
21
+ card = Trello::Card.from_json(card_details)
22
+
23
+ expect(card).to be_a(Trello::Card)
24
+ expect(card.name).to eq(cards_details.first['name'])
25
+ end
26
+ end
27
+ end
28
+
29
+ describe ".from_response" do
30
+ def example_class
31
+ @example_class ||= Class.new do
32
+ include Trello::JsonUtils
33
+
34
+ attr_accessor :name, :description
35
+
36
+ def initialize(options = {})
37
+ @name = options['name']
38
+ @description = options['description']
39
+ end
40
+ end
41
+ end
42
+
43
+ it 'converts json into an instance of a class' do
44
+ expect(example_class.from_response('{}')).to be_a example_class
45
+ end
46
+
47
+ it 'supplies the parsed json to the class ctor as a hash' do
48
+ json_text = '{"name" : "Jazz Kang", "description": "Plonker"}'
49
+
50
+ result = example_class.from_response json_text
51
+ expect(result.name).to eq("Jazz Kang")
52
+ expect(result.description).to eq("Plonker")
53
+ end
54
+
55
+ it 'can also handle arrays of instances of a class' do
56
+ json_text = <<-JSON
57
+ [
58
+ {"name" : "Jazz Kang", "description": "Plonker"},
59
+ {"name" : "Phil Murphy", "description": "Shoreditch hipster"}
60
+ ]
61
+ JSON
62
+
63
+ result = example_class.from_response json_text
64
+
65
+ expect(result).to be_an Array
66
+ expect(result.size).to eq 2
67
+ result.each do |parsed|
68
+ expect(parsed).to be_a example_class
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ describe Label do
5
+ include Helpers
6
+
7
+ let(:label) { client.find(:label, 'abcdef123456789123456789') }
8
+ let(:client) { Client.new }
9
+
10
+ before do
11
+ allow(client)
12
+ .to receive(:get)
13
+ .with("/labels/abcdef123456789123456789", {})
14
+ .and_return JSON.generate(label_details.first)
15
+ end
16
+
17
+ context "finding" do
18
+ let(:client) { Trello.client }
19
+
20
+ it "delegates to Trello.client#find" do
21
+ expect(client)
22
+ .to receive(:find)
23
+ .with(:label, 'abcdef123456789123456789', {})
24
+
25
+ Label.find('abcdef123456789123456789')
26
+ end
27
+
28
+ it "is equivalent to client#find" do
29
+ expect(Label.find('abcdef123456789123456789')).to eq(label)
30
+ end
31
+ end
32
+
33
+ context "creating" do
34
+ let(:client) { Trello.client }
35
+
36
+ it "creates a new record" do
37
+ expect(Label.new(label_details.first)).to be_valid
38
+ end
39
+
40
+ it "initializes all fields from response-like formatted hash" do
41
+ details = label_details.first
42
+ label = Label.new(details)
43
+ expect(label.color).to eq details['color']
44
+ expect(label.name).to eq details['name']
45
+ expect(label.id).to eq details['id']
46
+ expect(label.uses).to eq details['uses']
47
+ expect(label.board_id).to eq details['idBoard']
48
+ end
49
+
50
+ it "initializes required fields from options-like formatted hash" do
51
+ details = label_options
52
+ label = Label.new(details)
53
+ expect(label.name).to eq details[:name]
54
+ expect(label.board_id).to eq details[:board_id]
55
+ expect(label.color).to eq details[:color]
56
+ end
57
+
58
+ it 'must not be valid if not given a name' do
59
+ expect(Label.new('idBoard' => lists_details.first['board_id'])).to_not be_valid
60
+ end
61
+
62
+ it 'must not be valid if not given a board id' do
63
+ expect(Label.new('name' => lists_details.first['name'])).to_not be_valid
64
+ end
65
+
66
+ it 'creates a new record and saves it on Trello', refactor: true do
67
+ payload = {
68
+ name: 'Test Label',
69
+ board_id: 'abcdef123456789123456789',
70
+ }
71
+
72
+ result = JSON.generate(cards_details.first.merge(payload.merge(idBoard: boards_details.first['id'])))
73
+
74
+ expected_payload = {name: "Test Label", color: nil, idBoard: "abcdef123456789123456789" }
75
+
76
+ expect(client)
77
+ .to receive(:post)
78
+ .with("/labels", expected_payload)
79
+ .and_return result
80
+
81
+ label = Label.create(label_details.first.merge(payload.merge(board_id: boards_details.first['id'])))
82
+
83
+ expect(label).to be_a Label
84
+ end
85
+ end
86
+
87
+ context "updating" do
88
+ it "updating name does a put on the correct resource with the correct value" do
89
+ expected_new_name = "xxx"
90
+
91
+ payload = {
92
+ name: expected_new_name,
93
+ }
94
+
95
+ expect(client)
96
+ .to receive(:put)
97
+ .once
98
+ .with("/labels/abcdef123456789123456789", payload)
99
+
100
+ label.name = expected_new_name
101
+ label.save
102
+ end
103
+
104
+ it "updating color does a put on the correct resource with the correct value" do
105
+ expected_new_color = "purple"
106
+
107
+ payload = {
108
+ color: expected_new_color,
109
+ }
110
+
111
+ expect(client)
112
+ .to receive(:put)
113
+ .once
114
+ .with("/labels/abcdef123456789123456789", payload)
115
+
116
+ label.color = expected_new_color
117
+ label.save
118
+ end
119
+
120
+ it "can update with any valid color" do
121
+ %w(green yellow orange red purple blue sky lime pink black).each do |color|
122
+ allow(client)
123
+ .to receive(:put)
124
+ .with("/labels/abcdef123456789123456789", {color: color})
125
+ .and_return "not important"
126
+
127
+ label.color = color
128
+ label.save
129
+ expect(label.errors).to be_empty
130
+ end
131
+ end
132
+
133
+ it "throws an error when trying to update a label with an unknown colour" do
134
+ allow(client)
135
+ .to receive(:put)
136
+ .with("/labels/abcdef123456789123456789", {})
137
+ .and_return "not important"
138
+
139
+ label.color = 'mauve'
140
+ label.save
141
+
142
+ expect(label.errors.full_messages.to_sentence).to eq("Label color 'mauve' does not exist")
143
+ end
144
+ end
145
+
146
+ context "deleting" do
147
+ it "deletes the label" do
148
+ expect(client)
149
+ .to receive(:delete)
150
+ .with("/labels/#{label.id}")
151
+
152
+ label.delete
153
+ end
154
+ end
155
+
156
+ context "fields" do
157
+ it "gets its id" do
158
+ expect(label.id).to_not be_nil
159
+ end
160
+
161
+ it "gets its name" do
162
+ expect(label.name).to_not be_nil
163
+ end
164
+
165
+ it "gets its usage" do
166
+ expect(label.uses).to_not be_nil
167
+ end
168
+
169
+ it "gets its color" do
170
+ expect(label.color).to_not be_nil
171
+ end
172
+ end
173
+
174
+ context "boards" do
175
+ it "has a board" do
176
+ expect(client)
177
+ .to receive(:get)
178
+ .with("/boards/abcdef123456789123456789", {})
179
+ .and_return JSON.generate(boards_details.first)
180
+
181
+ expect(label.board).to_not be_nil
182
+ end
183
+ end
184
+
185
+ describe "#update_fields" do
186
+ it "does not set any fields when the fields argument is empty" do
187
+ expected = {
188
+ 'id' => 'id',
189
+ 'name' => 'name',
190
+ 'color' => 'color',
191
+ 'idBoard' => 'board_id',
192
+ 'uses' => 'uses'
193
+ }
194
+
195
+ label = Label.new(expected)
196
+
197
+ label.update_fields({})
198
+
199
+ expected.each do |key, value|
200
+ expect(label.send(value)).to eq expected[key]
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end