trello-fs 0.0.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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/Gemfile +3 -0
  4. data/README.md +52 -0
  5. data/examples/demo_board/A_List_of_Cards/README.md +6 -0
  6. data/examples/demo_board/A_List_of_Cards/TrelloFs_Features.md +14 -0
  7. data/examples/demo_board/A_List_of_Cards/TrelloFs_Installation.md +37 -0
  8. data/examples/demo_board/A_Second_List_of_Cards/A_card_with_an_image.md +13 -0
  9. data/examples/demo_board/A_Second_List_of_Cards/README.md +6 -0
  10. data/examples/demo_board/A_Second_List_of_Cards/This_one_has_a_puppy.md +13 -0
  11. data/examples/demo_board/Attachments/A_card_with_an_image/cats-cute-cat-animal-cute-grass-photo.jpg +0 -0
  12. data/examples/demo_board/Attachments/This_one_has_a_puppy/Puppy_2.jpg +0 -0
  13. data/examples/demo_board/Home +13 -0
  14. data/examples/demo_board/Labels/cats.md +5 -0
  15. data/examples/demo_board/Labels/images.md +6 -0
  16. data/examples/demo_board/Labels/no_name.md +4 -0
  17. data/examples/demo_board/Labels/puppies.md +5 -0
  18. data/examples/demo_board/Labels/readme.md +6 -0
  19. data/examples/demo_board/README.md +13 -0
  20. data/examples/demo_board.rb +8 -0
  21. data/examples/welcome_board/Advanced/Get_the_apps_for_iOS_Android_and_Windows_8.md +12 -0
  22. data/examples/welcome_board/Advanced/Need_help.md +10 -0
  23. data/examples/welcome_board/Advanced/README.md +10 -0
  24. data/examples/welcome_board/Advanced/Use_as_many_boards_as_you_want.md +8 -0
  25. data/examples/welcome_board/Advanced/Want_tips_usage_examples_or_API_info.md +8 -0
  26. data/examples/welcome_board/Advanced/Want_to_use_keyboard_shortcuts_We_have_them.md +10 -0
  27. data/examples/welcome_board/Advanced/Want_updates_on_new_features.md +14 -0
  28. data/examples/welcome_board/Attachments/You_can_attach_pictures_and_files/taco.png +0 -0
  29. data/examples/welcome_board/Basics/Click_on_a_card_to_see_whats_behind_it.md +8 -0
  30. data/examples/welcome_board/Basics/README.md +10 -0
  31. data/examples/welcome_board/Basics/This_is_a_card.md +8 -0
  32. data/examples/welcome_board/Basics/Welcome_to_Trello.md +8 -0
  33. data/examples/welcome_board/Basics/You_can_attach_pictures_and_files.md +13 -0
  34. data/examples/welcome_board/Basics/any_kind_of_hyperlink_.md +8 -0
  35. data/examples/welcome_board/Basics/or_checklists.md +8 -0
  36. data/examples/welcome_board/Home +31 -0
  37. data/examples/welcome_board/Intermediate/Drag_people_onto_a_card_to_indicate_that_theyre_responsible_for_it.md +8 -0
  38. data/examples/welcome_board/Intermediate/Finished_with_a_card_Archive_it.md +12 -0
  39. data/examples/welcome_board/Intermediate/Invite_your_team_to_this_board_using_the_Add_Members_button.md +8 -0
  40. data/examples/welcome_board/Intermediate/Make_as_many_lists_as_you_need.md +8 -0
  41. data/examples/welcome_board/Intermediate/README.md +11 -0
  42. data/examples/welcome_board/Intermediate/Try_dragging_cards_anywhere.md +8 -0
  43. data/examples/welcome_board/Intermediate/Use_color-coded_labels_for_organization.md +8 -0
  44. data/examples/welcome_board/Intermediate/You_can_change_the_board_background.md +8 -0
  45. data/examples/welcome_board/Labels/no_name.md +4 -0
  46. data/examples/welcome_board/Labels/red_one.md +6 -0
  47. data/examples/welcome_board/README.md +31 -0
  48. data/examples/welcome_board.rb +8 -0
  49. data/lib/trello-fs/attachment_builder.rb +60 -0
  50. data/lib/trello-fs/attachment_cleaner.rb +39 -0
  51. data/lib/trello-fs/board_builder.rb +61 -0
  52. data/lib/trello-fs/builder.rb +31 -0
  53. data/lib/trello-fs/card_builder.rb +87 -0
  54. data/lib/trello-fs/label_builder.rb +60 -0
  55. data/lib/trello-fs/labels_builder.rb +16 -0
  56. data/lib/trello-fs/list_builder.rb +68 -0
  57. data/lib/trello-fs/repository.rb +36 -0
  58. data/lib/trello-fs/repository_cleaner.rb +18 -0
  59. data/lib/trello-fs/string_to_file_name.rb +9 -0
  60. data/lib/trello-fs/trello_api.rb +83 -0
  61. data/lib/trello-fs/version.rb +3 -0
  62. data/lib/trello-fs.rb +8 -0
  63. data/spec/helpers/test_repository.rb +21 -0
  64. data/spec/spec_helper.rb +9 -0
  65. data/spec/trello-fs/attachment_builder_spec.rb +37 -0
  66. data/spec/trello-fs/attachment_cleaner_spec.rb +44 -0
  67. data/spec/trello-fs/board_builder_spec.rb +28 -0
  68. data/spec/trello-fs/card_builder_spec.rb +60 -0
  69. data/spec/trello-fs/label_builder_spec.rb +36 -0
  70. data/spec/trello-fs/list_builder_spec.rb +32 -0
  71. data/spec/trello-fs/repository_spec.rb +9 -0
  72. data/spec/trello-fs/string_to_file_name_spec.rb +19 -0
  73. data/spec/trello-fs/trello_api_spec.rb +144 -0
  74. data/trello-fs.gemspec +24 -0
  75. metadata +170 -0
@@ -0,0 +1,60 @@
1
+ require 'open-uri'
2
+
3
+ module TrelloFs
4
+ class AttachmentBuilder
5
+ attr_reader :card_builder, :attachment
6
+
7
+ def initialize(card_builder, attachment)
8
+ @card_builder = card_builder
9
+ @attachment = attachment
10
+ end
11
+
12
+ def build
13
+ return if already_downloaded?
14
+
15
+ download_and_save
16
+ end
17
+
18
+ def download_and_save
19
+ data = download
20
+ return unless data
21
+
22
+ FileUtils.mkpath(full_folder_path) unless File.exist? full_folder_path
23
+ File.open(path, 'wb') do |file|
24
+ file.write data
25
+ end
26
+ end
27
+
28
+ def path
29
+ File.join(full_folder_path, file_name)
30
+ end
31
+
32
+ def relative_path
33
+ File.join(folder_path, file_name)
34
+ end
35
+
36
+ def folder_path
37
+ File.join('Attachments', StringToFileName.convert(@card_builder.card_name))
38
+ end
39
+
40
+ def full_folder_path
41
+ File.join(repository.path, folder_path)
42
+ end
43
+
44
+ def file_name
45
+ @attachment.name.gsub(/ /, '_')
46
+ end
47
+
48
+ def already_downloaded?
49
+ File.exist? path
50
+ end
51
+
52
+ def download
53
+ open(@attachment.url).read
54
+ end
55
+
56
+ def repository
57
+ @card_builder.repository
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,39 @@
1
+ require 'fileutils'
2
+ require 'set'
3
+
4
+ module TrelloFs
5
+ class AttachmentCleaner
6
+ def initialize(repository, board)
7
+ @repository = repository
8
+ @board = board
9
+ end
10
+
11
+ def set_of_attachment_paths
12
+ @board.attachments.map do |attachment|
13
+ AttachmentBuilder.new(
14
+ CardBuilder.new(
15
+ ListBuilder.new(
16
+ BoardBuilder.new(@repository, @board),
17
+ attachment.card.list
18
+ ), attachment.card
19
+ ), attachment).path
20
+ end.to_set
21
+ end
22
+
23
+ def remove_old_attachments
24
+ new_attachments = set_of_attachment_paths
25
+
26
+ Dir.
27
+ glob(File.join(@repository.path, "Attachments/**/*")).
28
+ reject {|fn| File.directory?(fn) }.
29
+ each do |file|
30
+ next if new_attachments.include? file
31
+ FileUtils.rm(file)
32
+
33
+ # remove parent dir if empty
34
+ dirname = File.dirname(file)
35
+ FileUtils.rm_rf(dirname) if Dir[File.join(dirname, '*')].empty?
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,61 @@
1
+ module TrelloFs
2
+ class BoardBuilder
3
+ attr_reader :repository, :board
4
+
5
+ def initialize(repository, board)
6
+ @repository = repository
7
+ @board = board
8
+ end
9
+
10
+ def build
11
+ board.lists.each do |list|
12
+ ListBuilder.new(self, list).build
13
+ end
14
+ LabelsBuilder.new(@repository, @board).build
15
+
16
+ build_readme
17
+ end
18
+
19
+ def build_readme
20
+ readme_path = File.join(path, 'README.md')
21
+ File.open(readme_path, 'w') do |file|
22
+ file.write(readme_content)
23
+ end
24
+ end
25
+
26
+ def readme_content
27
+ [
28
+ "# [#{board_name}](#{@board.url})",
29
+ labels_content,
30
+ board.lists.map do |list|
31
+ list_builder = ListBuilder.new(self, list)
32
+ list_link = "[#{list_builder.list_name}](#{list_builder.file_name}/README.md)"
33
+
34
+ [
35
+ "## #{list_link}",
36
+ list_builder.content(true)
37
+ ].join("\n\n")
38
+ end.join("\n\n")
39
+ ].join("\n\n")
40
+ end
41
+
42
+ def labels_content
43
+ return '' unless @board.labels && @board.labels.any?
44
+
45
+ @board.labels.sort {|a, b| a.name <=> b.name }.
46
+ select {|lbl| lbl.cards.any? }.
47
+ map do |label|
48
+ label_builder = LabelBuilder.new(LabelsBuilder.new(@repository, @board), label)
49
+ "[`#{label_builder.label_name}`](#{label_builder.relative_path})"
50
+ end.join(' ')
51
+ end
52
+
53
+ def path
54
+ @repository.path
55
+ end
56
+
57
+ def board_name
58
+ @board.name
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ module TrelloFs
2
+ class Builder
3
+ attr_reader :config
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def build
10
+ repository = Repository.new config, self
11
+ board = TrelloApi.new(repository).board
12
+
13
+ # remove old files from the repo
14
+ RepositoryCleaner.new(repository).clean
15
+
16
+ BoardBuilder.new(repository, board).build
17
+ copy_readme_to_home(repository)
18
+
19
+ # remove old attachments
20
+ AttachmentCleaner.new(repository, board).remove_old_attachments
21
+ end
22
+
23
+ def copy_readme_to_home(repository)
24
+ FileUtils.cp(File.join(repository.path, 'README.md'), File.join(repository.path, 'Home'))
25
+ end
26
+
27
+ def trello_api_board(repository)
28
+ Trello::Board.find(repository.board_id)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,87 @@
1
+ module TrelloFs
2
+ class CardBuilder
3
+ def initialize(list_builder, card)
4
+ @card = card
5
+ @list_builder = list_builder
6
+ end
7
+
8
+ def build
9
+ @list_builder.build_path
10
+
11
+ attachment_paths = @card.attachments.map do |attachment|
12
+ attachment_builder = AttachmentBuilder.new(self, attachment)
13
+ attachment_builder.build
14
+ attachment_builder.relative_path
15
+ end
16
+
17
+ File.open(path, 'w') do |file|
18
+ file.write(content(attachment_paths))
19
+ end
20
+ end
21
+
22
+ def path
23
+ File.join(@list_builder.path, file_name)
24
+ end
25
+
26
+ def relative_path
27
+ File.join(@list_builder.file_name, file_name)
28
+ end
29
+
30
+ def file_name
31
+ "#{StringToFileName.convert(@card.name)}.md"
32
+ end
33
+
34
+ def content(attachment_paths = [])
35
+ labels = card_labels.map do |lbl|
36
+ label_builder = LabelBuilder.new(LabelsBuilder.new(repository, board), lbl)
37
+ "[`#{label_builder.label_name}`](../#{label_builder.relative_path})"
38
+ end.sort.join(' ')
39
+ list_name = @list_builder.list_name
40
+ board_name = @list_builder.board_name
41
+
42
+ [
43
+ "# [#{card_name}](#{@card.url})",
44
+ [
45
+ "[#{board_name}](../README.md)",
46
+ "[#{list_name}](README.md)"
47
+ ].join(' > '),
48
+ labels,
49
+ @card.desc,
50
+ attachments_content(attachment_paths)
51
+ ].join("\n\n")
52
+ end
53
+
54
+ def attachments_content(attachment_paths = [])
55
+ return '' unless attachment_paths.any?
56
+
57
+ links = attachment_paths.map do |path|
58
+ name = path.split('/').last
59
+ path = "../#{path}"
60
+ link = "[#{name}](#{path})"
61
+ if path.end_with?('.png') || path.end_with?('.jpg') || path.end_with?('gif')
62
+ "!#{link}"
63
+ else
64
+ link
65
+ end
66
+ end.join(" \n")
67
+
68
+ "\n\n## Attachments\n\n#{links}"
69
+ end
70
+
71
+ def card_name
72
+ @card.name
73
+ end
74
+
75
+ def repository
76
+ @list_builder.repository
77
+ end
78
+
79
+ def card_labels
80
+ @card_labels ||= @card.labels
81
+ end
82
+
83
+ def board
84
+ @list_builder.board_builder.board
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,60 @@
1
+ module TrelloFs
2
+ class LabelBuilder
3
+ def initialize(labels_builder, label)
4
+ @labels_builder = labels_builder
5
+ @repository = @labels_builder.repository
6
+ @board = @labels_builder.board
7
+ @label = label
8
+ end
9
+
10
+ def build
11
+ FileUtils.mkpath(folder_path)
12
+
13
+ File.open(path, 'w') do |f|
14
+ f.write content
15
+ end
16
+ end
17
+
18
+ def path
19
+ File.join(folder_path, file_name)
20
+ end
21
+
22
+ def relative_path
23
+ File.join('Labels', file_name)
24
+ end
25
+
26
+ def folder_path
27
+ File.join(@repository.path, 'Labels')
28
+ end
29
+
30
+ def file_name
31
+ "#{StringToFileName.convert(label_name)}.md"
32
+ end
33
+
34
+ def content
35
+ [
36
+ "# `#{label_name}`",
37
+ "[#{@board.name}](../README.md)",
38
+ card_links
39
+ ].join("\n\n")
40
+ end
41
+
42
+ def card_links
43
+ @label.cards.sort {|a,b| a.name <=> b.name }.map do |card|
44
+ card_builder = CardBuilder.new(
45
+ ListBuilder.new(
46
+ BoardBuilder.new(@repository, @board),
47
+ card.list
48
+ ), card
49
+ )
50
+ path = '../' + card_builder.relative_path
51
+ link = "[#{card_builder.card_name}](#{path})"
52
+ "- #{link}"
53
+ end.join("\n")
54
+ end
55
+
56
+ def label_name
57
+ @label.name.empty? ? 'no name' : @label.name
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,16 @@
1
+ module TrelloFs
2
+ class LabelsBuilder
3
+ attr_reader :repository, :board
4
+
5
+ def initialize(repository, board)
6
+ @repository = repository
7
+ @board = board
8
+ end
9
+
10
+ def build
11
+ @board.labels.each do |label|
12
+ LabelBuilder.new(self, label).build
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,68 @@
1
+ module TrelloFs
2
+ class ListBuilder
3
+ attr_reader :board_builder, :list
4
+
5
+ def initialize(board_builder, list)
6
+ @board_builder = board_builder
7
+ @list = list
8
+ end
9
+
10
+ def build
11
+ list.cards.each do |card|
12
+ CardBuilder.new(self, card).build
13
+ end
14
+
15
+ build_readme
16
+ end
17
+
18
+ def build_readme
19
+ build_path
20
+ readme_path = File.join(path, 'README.md')
21
+ File.open(readme_path, 'w') do |file|
22
+ file.write(readme_content)
23
+ end
24
+ end
25
+
26
+ def readme_content
27
+ [
28
+ "# #{list_name}",
29
+ "[#{board_name}](../README.md)",
30
+ content
31
+ ].join("\n\n")
32
+ end
33
+
34
+ def content(full_path = false)
35
+ @list.cards.map do |card|
36
+ cb = CardBuilder.new(self, card)
37
+ card_path = cb.file_name
38
+ card_path = File.join(file_name, card_path) if full_path
39
+
40
+ "- [#{cb.card_name}](#{card_path})"
41
+ end.join("\n")
42
+ end
43
+
44
+ def path
45
+ File.join(@board_builder.path, file_name)
46
+ end
47
+
48
+ def file_name
49
+ StringToFileName.convert(@list.name)
50
+ end
51
+
52
+ def build_path
53
+ FileUtils.mkpath(path) unless File.exist? path
54
+ end
55
+
56
+ def list_name
57
+ @list.name
58
+ end
59
+
60
+ def board_name
61
+ @board_builder.board_name
62
+ end
63
+
64
+ def repository
65
+ @board_builder.repository
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ module TrelloFs
2
+ class Repository
3
+ attr_reader :config
4
+
5
+ def initialize(config, builder = nil)
6
+ raise 'Wrong arguments' unless has_required_configuration?(config)
7
+
8
+ @config = config
9
+ @builder = builder
10
+ end
11
+
12
+ def path
13
+ @config[:path]
14
+ end
15
+
16
+ def board_id
17
+ @config[:board_id]
18
+ end
19
+
20
+ def developer_public_key
21
+ config[:developer_public_key]
22
+ end
23
+
24
+ def member_token
25
+ config[:member_token]
26
+ end
27
+
28
+ private
29
+
30
+ def has_required_configuration?(config)
31
+ config.has_key?(:path) &&
32
+ config.has_key?(:developer_public_key) &&
33
+ config.has_key?(:member_token)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ require 'fileutils'
2
+
3
+ module TrelloFs
4
+ class RepositoryCleaner
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def clean
10
+ Dir.entries(@repository.path).each do |path|
11
+ next if path.start_with? '.'
12
+ next if path == 'Attachments'
13
+
14
+ FileUtils.rm_rf File.join(@repository.path, path)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module TrelloFs
2
+ class StringToFileName
3
+ def self.convert(str)
4
+ str.gsub(/[^\w\s_-]+/, '').
5
+ gsub(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2').
6
+ gsub(/\s+/, '_')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,83 @@
1
+ require 'open-uri'
2
+ require 'json'
3
+
4
+ module TrelloFs
5
+ class TrelloApi
6
+ def initialize(repository)
7
+ @repository = repository
8
+ end
9
+
10
+ def board
11
+ @board ||= new_board
12
+ end
13
+
14
+ def new_board
15
+ json = download_board_json
16
+ board = OpenStruct.new(name: json['name'],
17
+ desc: json['desc'],
18
+ id: json['id'],
19
+ url: json['url'])
20
+ labels, lists = {}, {}
21
+ board.attachments = []
22
+
23
+ board.organization_name = json['organization']['displayName'] if json['organization']
24
+
25
+ json['labels'].each do |label|
26
+ labels[label['id']] = OpenStruct.new name: label['name'], id: label['id'], cards: []
27
+ end
28
+
29
+ json['lists'].each do |list|
30
+ lists[list['id']] = OpenStruct.new(name: list['name'],
31
+ id: list['id'],
32
+ board: board,
33
+ cards: [])
34
+ end
35
+
36
+ cards = json['cards'].map do |card|
37
+ list = lists[card['idList']]
38
+ c = OpenStruct.new(id: card['id'],
39
+ name: card['name'],
40
+ desc: card['desc'],
41
+ url: card['url'],
42
+ list: list)
43
+ list.cards << c
44
+
45
+ c.labels = card['idLabels'].map do |label_id|
46
+ label = labels[label_id]
47
+ label.cards << c
48
+ label
49
+ end
50
+
51
+ c.checklists = card['checklists'].map do |checklist|
52
+ OpenStruct.new(
53
+ name: checklist['name'],
54
+ items: checklist['checkItems'].map do |item|
55
+ OpenStruct.new(name: item['name'], state: item['state'])
56
+ end
57
+ )
58
+ end
59
+
60
+ c.attachments = card['attachments'].map do |attachment|
61
+ a = OpenStruct.new(name: attachment['name'],
62
+ url: attachment['url'],
63
+ id: attachment['id'],
64
+ card: c)
65
+ board.attachments << a
66
+ a
67
+ end
68
+
69
+ c
70
+ end
71
+
72
+ board.labels = labels.values
73
+ board.lists = lists.values
74
+
75
+ board
76
+ end
77
+
78
+ def download_board_json
79
+ url = "https://api.trello.com/1/boards/#{@repository.board_id}?key=#{@repository.developer_public_key}&token=#{@repository.member_token}&cards=all&lists=all&labels=all&card_checklists=all&card_attachments=true&organization=true"
80
+ JSON.parse(open(url).read)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module TrelloFs
2
+ VERSION = "0.0.1"
3
+ end
data/lib/trello-fs.rb ADDED
@@ -0,0 +1,8 @@
1
+ Dir[File.dirname(__FILE__) + "/**/*.rb"].each { |file| require file }
2
+ require 'fileutils'
3
+
4
+ module TrelloFs
5
+ def self.build(config)
6
+ Builder.new(config).build
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ require 'fileutils'
2
+
3
+ class TestRepository < TrelloFs::Repository
4
+ def initialize
5
+ super({
6
+ path: TestRepository.path,
7
+ developer_public_key: '',
8
+ member_token: ''
9
+ })
10
+ end
11
+
12
+ def self.path
13
+ p = 'tmp/test_repo'
14
+ FileUtils.mkpath p
15
+ p
16
+ end
17
+
18
+ def self.remove
19
+ FileUtils.rm_rf path
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path("../../lib/trello-fs", __FILE__)
2
+ Dir[File.dirname(__FILE__) + "/helpers/*.rb"].each { |file| require file }
3
+ require 'ostruct'
4
+
5
+ RSpec.configure do |config|
6
+ config.after :each do
7
+ TestRepository.remove
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe TrelloFs::AttachmentBuilder do
4
+ let(:attachment) { OpenStruct.new(id: '1', name: 'Attachment Name') }
5
+ let(:card) { OpenStruct.new(name: 'Card Name', attachments: [attachment]) }
6
+ let(:list) { OpenStruct.new(name: 'List Name', cards: [card]) }
7
+ let(:board) { OpenStruct.new(name: 'Board') }
8
+
9
+ let(:board_builder) { TrelloFs::BoardBuilder.new(TestRepository.new, board) }
10
+ let(:list_builder) { TrelloFs::ListBuilder.new(board_builder, list) }
11
+ let(:card_builder) { TrelloFs::CardBuilder.new(list_builder, card) }
12
+ let(:attachment_builder) { TrelloFs::AttachmentBuilder.new(card_builder, attachment) }
13
+
14
+ subject { attachment_builder }
15
+
16
+ before(:each) do
17
+ allow(attachment_builder).to receive(:download) { 'data' }
18
+ end
19
+
20
+ describe '#path' do
21
+ subject { attachment_builder.path }
22
+
23
+ it { should include 'Card_Name' }
24
+ it { should include 'Attachment Name' }
25
+ end
26
+
27
+ describe '#already_downloaded?' do
28
+ subject { attachment_builder.already_downloaded? }
29
+
30
+ it { should eq false }
31
+
32
+ it 'returns true after download' do
33
+ attachment_builder.build
34
+ should eq true
35
+ end
36
+ end
37
+ end