ruby-trello-czuger 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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