twirly 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +122 -0
  5. data/LICENSE +20 -0
  6. data/README.md +56 -0
  7. data/bin/twirly +6 -0
  8. data/config/initializers/trello.rb +4 -0
  9. data/lib/twirly/cli.rb +22 -0
  10. data/lib/twirly/commands/base.rb +14 -0
  11. data/lib/twirly/commands/fetch_user.rb +9 -0
  12. data/lib/twirly/commands/pick.rb +9 -0
  13. data/lib/twirly/commands/pull.rb +9 -0
  14. data/lib/twirly/commands.rb +6 -0
  15. data/lib/twirly/compiler.rb +26 -0
  16. data/lib/twirly/helpers/youtube.rb +37 -0
  17. data/lib/twirly/helpers.rb +3 -0
  18. data/lib/twirly/post.rb +81 -0
  19. data/lib/twirly/serializers/post.rb +21 -0
  20. data/lib/twirly/serializers/user.rb +20 -0
  21. data/lib/twirly/serializers.rb +6 -0
  22. data/lib/twirly/user.rb +31 -0
  23. data/lib/twirly/version.rb +3 -0
  24. data/lib/twirly.rb +45 -0
  25. data/spec/cli_spec.rb +24 -0
  26. data/spec/commands/fetch_user_spec.rb +16 -0
  27. data/spec/commands/pick_spec.rb +16 -0
  28. data/spec/commands/pull_spec.rb +10 -0
  29. data/spec/dummy/.bowerrc +3 -0
  30. data/spec/dummy/.gitignore +1 -0
  31. data/spec/dummy/Gemfile +12 -0
  32. data/spec/dummy/Gemfile.lock +116 -0
  33. data/spec/dummy/Guardfile +10 -0
  34. data/spec/dummy/assets/javascripts/app.coffee +3 -0
  35. data/spec/dummy/assets/javascripts/router.coffee +27 -0
  36. data/spec/dummy/assets/stylesheets/index.css.scss +17 -0
  37. data/spec/dummy/assets/stylesheets/partials/_header.css.scss +20 -0
  38. data/spec/dummy/assets/stylesheets/partials/_post.css.scss +19 -0
  39. data/spec/dummy/assets/stylesheets/partials/_reset.css.scss +425 -0
  40. data/spec/dummy/source/.gitkeep +0 -0
  41. data/spec/dummy/vendor/assets/bower_components/backbone/backbone.js +1608 -0
  42. data/spec/dummy/vendor/assets/bower_components/backbone/bower.json +9 -0
  43. data/spec/dummy/vendor/assets/bower_components/backbone/index.js +1 -0
  44. data/spec/dummy/vendor/assets/bower_components/jquery/bower.json +27 -0
  45. data/spec/dummy/vendor/assets/bower_components/jquery/dist/jquery.min.js +5 -0
  46. data/spec/dummy/vendor/assets/bower_components/underscore/bower.json +8 -0
  47. data/spec/dummy/vendor/assets/bower_components/underscore/underscore.js +1343 -0
  48. data/spec/factories/post.rb +9 -0
  49. data/spec/factories/trello/attachment.rb +17 -0
  50. data/spec/factories/trello/board.rb +20 -0
  51. data/spec/factories/trello/card.rb +56 -0
  52. data/spec/factories/trello/label.rb +19 -0
  53. data/spec/factories/trello/member.rb +16 -0
  54. data/spec/factories/user.rb +9 -0
  55. data/spec/post_spec.rb +155 -0
  56. data/spec/serializers/post_spec.rb +41 -0
  57. data/spec/serializers/user_spec.rb +34 -0
  58. data/spec/spec_helper.rb +19 -0
  59. data/spec/user_spec.rb +43 -0
  60. data/twirly.gemspec +38 -0
  61. data/twirly.yml.sample +4 -0
  62. metadata +324 -0
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :post, class: Twirly::Post do
3
+ skip_create
4
+
5
+ initialize_with do
6
+ Twirly::Post.new(FactoryGirl.create(:trello_card, :with_attachments))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ FactoryGirl.define do
2
+ factory :trello_attachment, class: Trello::Attachment do
3
+ skip_create
4
+
5
+ name { Faker::Lorem.word << '.png' }
6
+ id { SecureRandom.hex }
7
+ url 'https://trello-attachments.s3.amazonws.com/koko.png'
8
+ bytes { Random.new.rand(100..100_100) }
9
+ date { Time.now.to_s }
10
+ is_upload true
11
+
12
+ initialize_with do
13
+ attachment = Trello::Attachment.new attributes.stringify_keys
14
+ attachment
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ FactoryGirl.define do
2
+ factory :trello_board, class: Trello::Board do
3
+ skip_create
4
+
5
+ id { SecureRandom.hex }
6
+ short_id
7
+ name { "some board - #{short_id}" }
8
+ description 'this board is so great'
9
+ closed false
10
+ url "https://trello.com/b/NrYMTajk/foo-bar"
11
+ short_url "https://trello.com/b/NrYMTajk"
12
+ organization_id "53779c553c97bc8a506f83df"
13
+
14
+ initialize_with do
15
+ board = Trello::Board.new
16
+ attributes.each_pair { |k, v| board.attributes[k] = v }
17
+ board
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ FactoryGirl.define do
2
+ sequence :short_id
3
+ end
4
+
5
+ FactoryGirl.define do
6
+ factory :trello_card, class: Trello::Card do
7
+ skip_create
8
+
9
+ id { SecureRandom.hex }
10
+ short_id
11
+ name { "some card - #{short_id}" }
12
+ desc "---\ntags: pathway to [_], wesser\n---\n\n{% youtube 6TncafSqfyo %}"
13
+ due { Time.now }
14
+ closed false
15
+ url "https://trello.com/c/NrYMTajk/6-the-mushrooms-yard-of-my-head"
16
+ short_url "https://trello.com/c/NrYMTajk"
17
+ board_id "53779c553c97bc8a506f83df"
18
+ member_ids ["51597b21213b313631005042"]
19
+ list_id "53779c553c97bc8a506f83e0"
20
+ pos nil
21
+ last_activity_date { Time.now }
22
+ card_labels []
23
+ labels []
24
+ cover_image_id nil
25
+
26
+ association :attachments, factory: :trello_attachment
27
+
28
+ trait :published do
29
+ due { (DateTime.now - 1).to_time }
30
+
31
+ card_labels do
32
+ [ { name: 'published' } ]
33
+ end
34
+
35
+ labels do
36
+ [ { name: 'published' } ]
37
+ end
38
+ end
39
+
40
+ trait :unpublished do
41
+ due nil
42
+ end
43
+
44
+ trait :with_attachments do
45
+ after(:create) do |card|
46
+ card.stub(:attachments).and_return create_list(:trello_attachment, 5)
47
+ end
48
+ end
49
+
50
+ initialize_with do
51
+ card = Trello::Card.new
52
+ attributes.each_pair { |k, v| card.attributes[k] = v }
53
+ card
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ FactoryGirl.define do
2
+ factory :trello_label, class: Trello::Label do
3
+ skip_create
4
+
5
+ name { "some label - #{short_id}" }
6
+ color { %w(red green purple).sample }
7
+
8
+ trait :published do
9
+ name 'published'
10
+ color 'green'
11
+ end
12
+
13
+ initialize_with do
14
+ label = Trello::Label.new
15
+ attributes.each_pair { |k, v| card.attributes[k] = v }
16
+ label
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ FactoryGirl.define do
2
+ factory :trello_member, class: Trello::Member do
3
+ skip_create
4
+
5
+ id { SecureRandom.hex }
6
+ username { Faker::Internet.user_name }
7
+ email { Faker::Internet.free_email }
8
+ bio { Faker::Lorem.sentence }
9
+
10
+ initialize_with do
11
+ member = Trello::Member.new
12
+ attributes.each_pair { |k, v| member.attributes[k] = v }
13
+ member
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :user, class: Twirly::User do
3
+ skip_create
4
+
5
+ initialize_with do
6
+ Twirly::User.new(FactoryGirl.create(:trello_member))
7
+ end
8
+ end
9
+ end
data/spec/post_spec.rb ADDED
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twirly::Post do
4
+ let(:trello_board) { create(:trello_board) }
5
+ let(:trello_card) { create(:trello_card) }
6
+ let(:front_matter_content) do
7
+ <<-YAML.strip_heredoc.strip
8
+ ---
9
+ important: true
10
+ tags: idm, punk, electro
11
+ ---
12
+ YAML
13
+ end
14
+
15
+ let(:markdown_content) do
16
+ <<-MDN.strip_heredoc.strip
17
+ # A post about cats
18
+ > Everybody loves cats
19
+ {% youtube 320 280 4-IpnaqBhT4 %}
20
+ MDN
21
+ end
22
+
23
+ let(:post) { Twirly::Post.new(trello_card) }
24
+ subject { post }
25
+
26
+ describe '#card' do
27
+ it 'returns a Trello::Card' do
28
+ expect(subject.card.class).to eq(Trello::Card)
29
+ end
30
+ end
31
+
32
+ describe '#title' do
33
+ it "is delegated to the card's name" do
34
+ expect(subject.title).to eq(subject.card.name)
35
+ end
36
+ end
37
+
38
+ describe '#updated_at' do
39
+ it "is delegated to the card's last_activity_date" do
40
+ expect(subject.updated_at).to eq(subject.card.last_activity_date)
41
+ end
42
+ end
43
+
44
+ describe '#created_at' do
45
+ it "is delegated to the card's due" do
46
+ expect(subject.created_at).to eq(subject.card.due)
47
+ end
48
+ end
49
+
50
+ describe '#published_at' do
51
+ it "is delegated to the card's due" do
52
+ expect(subject.published_at).to eq(subject.card.due)
53
+ end
54
+ end
55
+
56
+ describe '#card_id' do
57
+ it "is delegated to the card's id" do
58
+ expect(subject.card_id).to eq(subject.card.short_id)
59
+ end
60
+ end
61
+
62
+ describe '#short_published_at' do
63
+ subject { post.short_published_at }
64
+
65
+ it { expect(subject).to eq(trello_card.due.strftime('%Y-%m-%d')) }
66
+ end
67
+
68
+ describe '#slug' do
69
+ subject { post.slug }
70
+ let(:slug) {"#{post.short_published_at}-#{post.title.parameterize}-#{post.card_id}" }
71
+
72
+ it { expect(subject).to eq(slug) }
73
+ end
74
+
75
+ describe '#authors' do
76
+ before do
77
+ subject.card.stub(:members).and_return(create_list(:trello_member, 3))
78
+ end
79
+
80
+ it "returns the decorated as Twirly::User(s) card members" do
81
+ expect(subject.authors.map(&:username))
82
+ .to match_array(subject.card.members.map(&:username))
83
+ end
84
+ end
85
+
86
+ describe '#tags' do
87
+ pending
88
+ end
89
+
90
+ describe '#body' do
91
+ pending
92
+ end
93
+
94
+ describe '#published?' do
95
+ context 'card is published (has published_at and the "published" label' do
96
+ let(:subject) do
97
+ post = Twirly::Post.new(create(:trello_card, :published))
98
+ post.card.stub(:labels).and_return([double(name: 'published')])
99
+ post
100
+ end
101
+
102
+ it 'returns true' do
103
+ expect(subject).to be_published
104
+ end
105
+ end
106
+
107
+ context 'card is not published (has published_at and the "published" label' do
108
+ let(:subject) { Twirly::Post.new(create(:trello_card, :unpublished)) }
109
+
110
+ it 'returns false' do
111
+ expect(subject).to_not be_published
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '.published' do
117
+ let(:unpublished_cards) do
118
+ create_list(:trello_card, 3, :unpublished).map do |card|
119
+ card.stub(:labels).and_return([])
120
+ card
121
+ end
122
+ end
123
+
124
+ let(:published_cards) do
125
+ create_list(:trello_card, 4, :published).map do |card|
126
+ card.stub(:labels).and_return([double(name: 'published')])
127
+ card
128
+ end
129
+ end
130
+
131
+ before do
132
+ Trello::Board.stub(:find).and_return(trello_board)
133
+ Twirly.board.stub(:cards).and_return(unpublished_cards + published_cards)
134
+ end
135
+
136
+ it 'returns only posts decorating published cards' do
137
+ expect(Twirly::Post.published.map(&:card_id)).
138
+ to match_array(published_cards.map(&:short_id))
139
+ end
140
+ end
141
+
142
+ describe '.find' do
143
+ let(:matching_card) { create(:trello_card, short_id: 42) }
144
+ let(:non_matching_card) { create(:trello_card, short_id: 404) }
145
+
146
+ before do
147
+ Trello::Board.stub(:find).and_return(trello_board)
148
+ Twirly.board.stub(:cards).and_return([matching_card, non_matching_card])
149
+ end
150
+
151
+ it 'returns a card from the registered board with a matching trello short_id' do
152
+ expect(Twirly::Post.find(42).card_id).to eq(42)
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twirly::Serializers::Post do
4
+ let(:trello_board) { create(:trello_board) }
5
+ let(:trello_card) { create(:trello_card, :with_attachments) }
6
+
7
+ before do
8
+ trello_card.stub_chain(:list, :name).and_return 'music'
9
+ trello_card.stub(:labels).and_return([double(name: 'post-punk')])
10
+ end
11
+
12
+ let(:post) { Twirly::Post.new(trello_card) }
13
+
14
+ describe '#as_json' do
15
+ subject { post.as_json }
16
+
17
+ it 'is a Hash' do
18
+ expect(subject.as_json).to be_a(Hash)
19
+ end
20
+
21
+ it 'has a root key' do
22
+ expect(subject[:post]).to be
23
+ end
24
+
25
+ describe 'representation attributes' do
26
+ subject { post.as_json[:post] }
27
+
28
+ its(:keys) { should match_array(%w[card_id title category tags
29
+ updated_at published_at].
30
+ map(&:to_sym)) }
31
+ end
32
+ end
33
+
34
+ describe '#to_json' do
35
+ subject { post.to_json }
36
+
37
+ it 'is a String' do
38
+ expect(subject.to_json).to be_a(String)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twirly::Serializers::User do
4
+ let(:trello_member) { create(:trello_member) }
5
+
6
+ let(:user) { Twirly::User.new(trello_member) }
7
+
8
+ describe '#as_json' do
9
+ subject { user.as_json }
10
+
11
+ it 'is a Hash' do
12
+ expect(subject.as_json).to be_a(Hash)
13
+ end
14
+
15
+ it 'has a root key' do
16
+ expect(subject[:user]).to be
17
+ end
18
+
19
+ describe 'representation attributes' do
20
+ subject { user.as_json[:user] }
21
+
22
+ its(:keys) { should match_array(%w[id username full_name bio avatar_url].
23
+ map(&:to_sym)) }
24
+ end
25
+ end
26
+
27
+ describe '#to_json' do
28
+ subject { user.to_json }
29
+
30
+ it 'is a String' do
31
+ expect(subject.to_json).to be_a(String)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ require 'twirly'
2
+ require 'factory_girl'
3
+ require 'faker'
4
+
5
+ RSpec.configure do |config|
6
+ # Formatting
7
+ config.formatter = :documentation
8
+ config.color_enabled = true
9
+
10
+ # Filtering
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run focus: true
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+
15
+ Dir['./spec/support/**/*.rb'].each(&method(:require))
16
+ Dir['./spec/factories/**/*.rb'].each(&method(:require))
17
+
18
+ config.include FactoryGirl::Syntax::Methods
19
+ end
data/spec/user_spec.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twirly::User do
4
+ let(:trello_member) { create(:trello_member) }
5
+
6
+ subject { Twirly::User.new(trello_member) }
7
+
8
+ describe '#member' do
9
+ it 'returns a Trello::Member' do
10
+ expect(subject.member.class).to eq(Trello::Member)
11
+ end
12
+ end
13
+
14
+ describe '.all' do
15
+ let(:board_members) { create_list(:trello_member, 3) }
16
+ let(:trello_board) { create(:trello_board) }
17
+
18
+ before do
19
+ Trello::Board.stub(:find).and_return(trello_board)
20
+ Twirly.board.stub(:members).and_return(board_members)
21
+ Twirly::User.any_instance.stub(:refresh!)
22
+ end
23
+
24
+ it 'returns only users decorating board members' do
25
+ expect(Twirly::User.all.map(&:username)).
26
+ to match_array(board_members.map(&:username))
27
+ end
28
+ end
29
+
30
+ describe '.find_by_username' do
31
+ let(:matching_member) { create(:trello_member, username: 'zorbash') }
32
+ let(:non_matching_member) { create(:trello_member, username: 'zoidberg') }
33
+
34
+ before do
35
+ Twirly.board.stub(:members).and_return([matching_member, non_matching_member])
36
+ Twirly::User.any_instance.stub(:refresh!)
37
+ end
38
+
39
+ it 'returns a user from the registered board with a matching trello username' do
40
+ expect(Twirly::User.find_by_username('zorbash').username).to eq('zorbash')
41
+ end
42
+ end
43
+ end
data/twirly.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'twirly/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'twirly'
8
+ spec.version = Twirly::VERSION
9
+ spec.authors = ['Dimitris Zorbas']
10
+ spec.email = ['zorbash@skroutz.gr']
11
+ spec.description = <<-DESC
12
+ Publishing platform using trello
13
+ DESC
14
+
15
+ spec.summary = %q{Publishing platform using trello}
16
+ spec.homepage = 'https://github.com/Zorbash/twirly'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files`.split($/)
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'pry'
27
+ spec.add_development_dependency 'pry-nav'
28
+ spec.add_development_dependency 'rspec', '~> 2.14.1'
29
+ spec.add_development_dependency 'guard-rspec'
30
+ spec.add_development_dependency 'rubocop'
31
+ spec.add_development_dependency 'faker'
32
+ spec.add_development_dependency 'factory_girl'
33
+
34
+ spec.add_dependency 'thor', '~> 1.19'
35
+ spec.add_dependency 'ruby-trello', '~> 1.1'
36
+ spec.add_dependency 'liquid', '~> 3.0'
37
+ spec.add_dependency 'json', '>= 1.8.1'
38
+ end
data/twirly.yml.sample ADDED
@@ -0,0 +1,4 @@
1
+ trello_key: 'deadc256a00ab5aa2892ce753b3bad'
2
+ trello_secret: 'dead340e6f272c7e0f85c5be3dd49f5d225f489efc6fa54306dc5712771bad'
3
+ organization: 'some_organization'
4
+ publishing_board: 'iPAnh67A'