troo 0.0.1 → 0.0.2

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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +0 -1
  5. data/Guardfile +6 -0
  6. data/LICENSE.txt +1 -0
  7. data/README.md +46 -3
  8. data/Rakefile +11 -0
  9. data/bin/troo +12 -0
  10. data/configuration.yml.example +7 -0
  11. data/features/add_board.feature +1 -0
  12. data/features/add_card.feature +1 -0
  13. data/features/add_comment.feature +1 -0
  14. data/features/add_list.feature +1 -0
  15. data/features/cleanup.feature +0 -0
  16. data/features/move_card_to_list.feature +1 -0
  17. data/features/refresh.feature +1 -0
  18. data/features/set_default.feature +7 -0
  19. data/features/show_board.feature +1 -0
  20. data/features/show_boards.feature +1 -0
  21. data/features/show_card.feature +1 -0
  22. data/features/show_comments.feature +1 -0
  23. data/features/show_list.feature +1 -0
  24. data/features/status.feature +1 -0
  25. data/features/step_definitions/troo_steps.rb +0 -0
  26. data/features/support/env.rb +31 -0
  27. data/features/troo.feature +1 -0
  28. data/features/version.feature +8 -0
  29. data/lib/troo.rb +24 -2
  30. data/lib/troo/actions/create_board.rb +43 -0
  31. data/lib/troo/actions/create_card.rb +43 -0
  32. data/lib/troo/actions/create_comment.rb +44 -0
  33. data/lib/troo/actions/create_list.rb +41 -0
  34. data/lib/troo/actions/move_card.rb +36 -0
  35. data/lib/troo/actions/refresh_all.rb +79 -0
  36. data/lib/troo/actions/set_default.rb +35 -0
  37. data/lib/troo/cli/add_cli.rb +83 -0
  38. data/lib/troo/cli/default_cli.rb +37 -0
  39. data/lib/troo/cli/main_cli.rb +130 -0
  40. data/lib/troo/cli/show_cli.rb +83 -0
  41. data/lib/troo/cli/thor_fixes.rb +9 -0
  42. data/lib/troo/display/board_decorator.rb +58 -0
  43. data/lib/troo/display/board_presenter.rb +65 -0
  44. data/lib/troo/display/card_decorator.rb +105 -0
  45. data/lib/troo/display/card_presenter.rb +27 -0
  46. data/lib/troo/display/comment_decorator.rb +32 -0
  47. data/lib/troo/display/comment_presenter.rb +35 -0
  48. data/lib/troo/display/decorator_helpers.rb +76 -0
  49. data/lib/troo/display/list_decorator.rb +53 -0
  50. data/lib/troo/display/list_presenter.rb +43 -0
  51. data/lib/troo/display/member_decorator.rb +24 -0
  52. data/lib/troo/display/member_presenter.rb +59 -0
  53. data/lib/troo/external/board.rb +49 -0
  54. data/lib/troo/external/board_adaptor.rb +43 -0
  55. data/lib/troo/external/card.rb +70 -0
  56. data/lib/troo/external/card_adaptor.rb +78 -0
  57. data/lib/troo/external/comment.rb +64 -0
  58. data/lib/troo/external/comment_adaptor.rb +53 -0
  59. data/lib/troo/external/list.rb +58 -0
  60. data/lib/troo/external/list_adaptor.rb +48 -0
  61. data/lib/troo/external/member.rb +52 -0
  62. data/lib/troo/external/member_adaptor.rb +63 -0
  63. data/lib/troo/models/board.rb +26 -0
  64. data/lib/troo/models/board_persistence.rb +53 -0
  65. data/lib/troo/models/board_retrieval.rb +45 -0
  66. data/lib/troo/models/card.rb +54 -0
  67. data/lib/troo/models/card_persistence.rb +53 -0
  68. data/lib/troo/models/card_retrieval.rb +49 -0
  69. data/lib/troo/models/comment.rb +32 -0
  70. data/lib/troo/models/comment_persistence.rb +53 -0
  71. data/lib/troo/models/comment_retrieval.rb +32 -0
  72. data/lib/troo/models/list.rb +27 -0
  73. data/lib/troo/models/list_persistence.rb +53 -0
  74. data/lib/troo/models/list_retrieval.rb +45 -0
  75. data/lib/troo/models/member.rb +18 -0
  76. data/lib/troo/models/member_persistence.rb +53 -0
  77. data/lib/troo/models/member_retrieval.rb +36 -0
  78. data/lib/troo/models/model_helpers.rb +32 -0
  79. data/lib/troo/models/refresh.rb +23 -0
  80. data/lib/troo/presentation/template.rb +31 -0
  81. data/lib/troo/troo.rb +69 -0
  82. data/lib/troo/version.rb +2 -1
  83. data/lib/troo/views/card.erb +17 -0
  84. data/lib/troo/views/comment.erb +3 -0
  85. data/logs/.gitkeep +0 -0
  86. data/test/cassettes/board_by_id.yml +59 -0
  87. data/test/cassettes/boards_all.yml +118 -0
  88. data/test/cassettes/card_by_card_id.yml +58 -0
  89. data/test/cassettes/cards_by_board_id.yml +117 -0
  90. data/test/cassettes/cards_by_list_id.yml +114 -0
  91. data/test/cassettes/comments_by_board_id.yml +122 -0
  92. data/test/cassettes/comments_by_card_id.yml +114 -0
  93. data/test/cassettes/comments_by_list_id.yml +109 -0
  94. data/test/cassettes/create_board.yml +62 -0
  95. data/test/cassettes/create_card.yml +63 -0
  96. data/test/cassettes/create_comment.yml +67 -0
  97. data/test/cassettes/create_list.yml +60 -0
  98. data/test/cassettes/list_by_list_id.yml +56 -0
  99. data/test/cassettes/lists_by_board_id.yml +118 -0
  100. data/test/cassettes/member_by_member_id.yml +60 -0
  101. data/test/cassettes/members_by_board_id.yml +109 -0
  102. data/test/cassettes/move_card.yml +61 -0
  103. data/test/lib/troo/actions/create_board_test.rb +47 -0
  104. data/test/lib/troo/actions/create_card_test.rb +54 -0
  105. data/test/lib/troo/actions/create_comment_test.rb +49 -0
  106. data/test/lib/troo/actions/create_list_test.rb +49 -0
  107. data/test/lib/troo/actions/move_card_test.rb +46 -0
  108. data/test/lib/troo/actions/refresh_all_test.rb +68 -0
  109. data/test/lib/troo/actions/set_default_test.rb +44 -0
  110. data/test/lib/troo/cli/add_cli_test.rb +216 -0
  111. data/test/lib/troo/cli/default_cli_test.rb +79 -0
  112. data/test/lib/troo/cli/main_cli_test.rb +232 -0
  113. data/test/lib/troo/cli/show_cli_test.rb +221 -0
  114. data/test/lib/troo/cli/thor_fixes_test.rb +21 -0
  115. data/test/lib/troo/display/board_decorator_test.rb +126 -0
  116. data/test/lib/troo/display/board_presenter_test.rb +77 -0
  117. data/test/lib/troo/display/card_decorator_test.rb +221 -0
  118. data/test/lib/troo/display/card_presenter_test.rb +38 -0
  119. data/test/lib/troo/display/comment_decorator_test.rb +65 -0
  120. data/test/lib/troo/display/comment_presenter_test.rb +47 -0
  121. data/test/lib/troo/display/decorator_helpers_test.rb +7 -0
  122. data/test/lib/troo/display/list_decorator_test.rb +98 -0
  123. data/test/lib/troo/display/list_presenter_test.rb +48 -0
  124. data/test/lib/troo/display/member_decorator_test.rb +42 -0
  125. data/test/lib/troo/display/member_presenter_test.rb +70 -0
  126. data/test/lib/troo/external/board_adaptor_test.rb +36 -0
  127. data/test/lib/troo/external/board_test.rb +69 -0
  128. data/test/lib/troo/external/card_adaptor_test.rb +50 -0
  129. data/test/lib/troo/external/card_test.rb +108 -0
  130. data/test/lib/troo/external/comment_adaptor_test.rb +41 -0
  131. data/test/lib/troo/external/comment_test.rb +88 -0
  132. data/test/lib/troo/external/list_adaptor_test.rb +38 -0
  133. data/test/lib/troo/external/list_test.rb +65 -0
  134. data/test/lib/troo/external/member_adaptor_test.rb +44 -0
  135. data/test/lib/troo/external/member_test.rb +65 -0
  136. data/test/lib/troo/models/board_persistence_test.rb +61 -0
  137. data/test/lib/troo/models/board_retrieval_test.rb +93 -0
  138. data/test/lib/troo/models/board_test.rb +50 -0
  139. data/test/lib/troo/models/card_persistence_test.rb +60 -0
  140. data/test/lib/troo/models/card_retrieval_test.rb +101 -0
  141. data/test/lib/troo/models/card_test.rb +102 -0
  142. data/test/lib/troo/models/comment_persistence_test.rb +65 -0
  143. data/test/lib/troo/models/comment_retrieval_test.rb +46 -0
  144. data/test/lib/troo/models/comment_test.rb +59 -0
  145. data/test/lib/troo/models/list_persistence_test.rb +60 -0
  146. data/test/lib/troo/models/list_retrieval_test.rb +93 -0
  147. data/test/lib/troo/models/list_test.rb +53 -0
  148. data/test/lib/troo/models/member_persistence_test.rb +59 -0
  149. data/test/lib/troo/models/member_retrieval_test.rb +58 -0
  150. data/test/lib/troo/models/member_test.rb +44 -0
  151. data/test/lib/troo/models/model_helpers_test.rb +103 -0
  152. data/test/lib/troo/models/refresh_test.rb +45 -0
  153. data/test/lib/troo/presentation/template_test.rb +40 -0
  154. data/test/support/fabrication.rb +56 -0
  155. data/test/support/template.erb +3 -0
  156. data/test/support/vcr_setup.rb +36 -0
  157. data/test/test_helper.rb +30 -0
  158. data/troo.gemspec +24 -5
  159. metadata +501 -23
@@ -0,0 +1,88 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ module External
5
+ describe Comment do
6
+ let(:described_class) { Comment }
7
+ let(:options) { {} }
8
+
9
+ describe ".initialize" do
10
+ subject { described_class.new("some_id", options) }
11
+
12
+ it "assigns the external_id" do
13
+ subject.instance_variable_get("@external_id").must_equal("some_id")
14
+ end
15
+
16
+ it "assigns the options" do
17
+ subject.instance_variable_get("@options").must_equal(options)
18
+ end
19
+ end
20
+
21
+ describe "when the mode is board" do
22
+ before { VCR.insert_cassette(:comments_by_board_id, decode_compressed_response: true) }
23
+ after { VCR.eject_cassette }
24
+
25
+ let(:board_id) { "526d8e130a14a9d846001d96" }
26
+ let(:options) { { mode: :board } }
27
+
28
+ subject { described_class.fetch(board_id, options) }
29
+
30
+ it "returns multiple comments" do
31
+ subject.size.must_equal(2)
32
+ end
33
+
34
+ context "when the board cannot be found" do
35
+ before { Trello::Board.stubs(:find).raises(Trello::Error) }
36
+
37
+ it "returns an empty collection" do
38
+ subject.must_equal([])
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "when the mode is list" do
44
+ before { VCR.insert_cassette(:comments_by_list_id, decode_compressed_response: true) }
45
+ after { VCR.eject_cassette }
46
+
47
+ let(:list_id) { "526d8e130a14a9d846001d97" }
48
+ let(:options) { { mode: :list } }
49
+
50
+ subject { described_class.fetch(list_id, options) }
51
+
52
+ it "returns comments with the list_id" do
53
+ subject.size.must_equal(0)
54
+ end
55
+
56
+ context "when the list cannot be found" do
57
+ before { Trello::List.stubs(:find).raises(Trello::Error) }
58
+
59
+ it "returns an empty collection" do
60
+ subject.must_equal([])
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "when the mode is card" do
66
+ before { VCR.insert_cassette(:comments_by_card_id, decode_compressed_response: true) }
67
+ after { VCR.eject_cassette }
68
+
69
+ let(:card_id) { "526d8f19ddb279532e005259" }
70
+ let(:options) { { mode: :card } }
71
+
72
+ subject { described_class.fetch(card_id, options) }
73
+
74
+ it "returns a comment with the card_id" do
75
+ subject.size.must_equal(2)
76
+ end
77
+
78
+ context "when the card cannot be found" do
79
+ before { Trello::Card.stubs(:find).raises(Trello::Error) }
80
+
81
+ it "returns an empty collection" do
82
+ subject.must_equal([])
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ module External
5
+ describe ListAdaptor do
6
+ let(:described_class) { ListAdaptor }
7
+ let(:resource) { OpenStruct.new({
8
+ board_id: "526d8e130a14a9d846001d96",
9
+ id: "526d8e130a14a9d846001d97",
10
+ name: "My Test List",
11
+ pos: 32768,
12
+ closed: false,
13
+ }) }
14
+
15
+ describe "#initialize" do
16
+ subject { described_class.new(resource) }
17
+
18
+ it "assigns the resource to an instance variable" do
19
+ subject.instance_variable_get("@resource").must_equal(resource)
20
+ end
21
+ end
22
+
23
+ describe "#adapted" do
24
+ subject { described_class.adapt(resource) }
25
+
26
+ it "returns an adapted resource suitable for local persistence" do
27
+ subject.must_equal({
28
+ external_board_id: "526d8e130a14a9d846001d96",
29
+ external_list_id: "526d8e130a14a9d846001d97",
30
+ name: "My Test List",
31
+ position: "32768",
32
+ closed: "false",
33
+ })
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,65 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ module External
5
+ describe List do
6
+ let(:described_class) { List }
7
+
8
+ describe ".initialize" do
9
+ subject { described_class.new("some_id", {}) }
10
+
11
+ it "assigns the external_id" do
12
+ subject.instance_variable_get("@external_id").must_equal "some_id"
13
+ end
14
+
15
+ it "assigns the options" do
16
+ subject.instance_variable_get("@options").must_equal({})
17
+ end
18
+ end
19
+
20
+ describe "when the mode is board" do
21
+ before { VCR.insert_cassette(:lists_by_board_id, decode_compressed_response: true) }
22
+ after { VCR.eject_cassette }
23
+
24
+ let(:board_id) { "526d8e130a14a9d846001d96" }
25
+ let(:options) { { mode: :board } }
26
+
27
+ subject { described_class.fetch(board_id, options) }
28
+
29
+ it "returns multiple lists" do
30
+ subject.size.must_equal(4)
31
+ end
32
+
33
+ context "when the board cannot be found" do
34
+ before { Trello::Board.stubs(:find).raises(Trello::Error) }
35
+
36
+ it "returns an empty collection" do
37
+ subject.must_equal([])
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "when the mode is list" do
43
+ before { VCR.insert_cassette(:list_by_list_id, decode_compressed_response: true) }
44
+ after { VCR.eject_cassette }
45
+
46
+ let(:list_id) { "526d8e130a14a9d846001d97" }
47
+ let(:options) { { mode: :list } }
48
+
49
+ subject { described_class.fetch(list_id, options) }
50
+
51
+ it "returns a list with the list_id" do
52
+ subject.size.must_equal(1)
53
+ end
54
+
55
+ context "when the list cannot be found" do
56
+ before { Trello::List.stubs(:find).raises(Trello::Error) }
57
+
58
+ it "returns an empty collection" do
59
+ subject.must_equal([])
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ module External
5
+ describe MemberAdaptor do
6
+ let(:described_class) { MemberAdaptor }
7
+ let(:resource) { OpenStruct.new({
8
+ id: "5195fdb5a8c01a2318004f5d",
9
+ username: "gavinlaking1",
10
+ email: "gavinlaking@gmail.com",
11
+ full_name: "Gavin Laking",
12
+ initials: "GL",
13
+ avatar_id: "some_avatar_id",
14
+ bio: "some bio",
15
+ url: "http://www.gavinlaking.name/"
16
+ }) }
17
+
18
+ describe "#initialize" do
19
+ subject { described_class.new(resource) }
20
+
21
+ it "assigns the resource to an instance variable" do
22
+ subject.instance_variable_get("@resource").must_equal(resource)
23
+ end
24
+ end
25
+
26
+ describe "#adapted" do
27
+ subject { described_class.adapt(resource) }
28
+
29
+ it "returns an adapted resource suitable for local persistence" do
30
+ subject.must_equal({
31
+ external_member_id: "5195fdb5a8c01a2318004f5d",
32
+ username: "gavinlaking1",
33
+ email: "gavinlaking@gmail.com",
34
+ full_name: "Gavin Laking",
35
+ initials: "GL",
36
+ avatar_id: "some_avatar_id",
37
+ bio: "some bio",
38
+ url: "http://www.gavinlaking.name/",
39
+ })
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,65 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ module External
5
+ describe Member do
6
+ let(:described_class) { Member }
7
+
8
+ describe ".initialize" do
9
+ subject { described_class.new("some_id", {}) }
10
+
11
+ it "assigns the external_id" do
12
+ subject.instance_variable_get("@external_id").must_equal("some_id")
13
+ end
14
+
15
+ it "assigns the options" do
16
+ subject.instance_variable_get("@options").must_equal({})
17
+ end
18
+ end
19
+
20
+ describe "when the mode is board" do
21
+ before { VCR.insert_cassette(:members_by_board_id, decode_compressed_response: true) }
22
+ after { VCR.eject_cassette }
23
+
24
+ let(:board_id) { "526d8e130a14a9d846001d96" }
25
+ let(:options) { { mode: :board } }
26
+
27
+ subject { described_class.fetch(board_id, options) }
28
+
29
+ it "returns multiple members" do
30
+ subject.size.must_equal(1)
31
+ end
32
+
33
+ context "when the board cannot be found" do
34
+ before { Trello::Board.stubs(:find).raises(Trello::Error) }
35
+
36
+ it "returns an empty collection" do
37
+ subject.must_equal([])
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "when the mode is member" do
43
+ before { VCR.insert_cassette(:member_by_member_id, decode_compressed_response: true) }
44
+ after { VCR.eject_cassette }
45
+
46
+ let(:member_id) { "5195fdb5a8c01a2318004f5d" }
47
+ let(:options) { { mode: :member } }
48
+
49
+ subject { described_class.fetch(member_id, options) }
50
+
51
+ it "returns a member with the member_id" do
52
+ subject.size.must_equal(1)
53
+ end
54
+
55
+ context "when the member cannot be found" do
56
+ before { Trello::Member.stubs(:find).raises(Trello::Error) }
57
+
58
+ it "returns an empty collection" do
59
+ subject.must_equal([])
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,61 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ describe BoardPersistence do
5
+ let(:described_class) { BoardPersistence }
6
+ let(:resource) { OpenStruct.new({
7
+ id: "526d8e130a14a9d846001d96",
8
+ name: resource_name,
9
+ description: "A very brief description...",
10
+ closed: false
11
+ }) }
12
+ let(:resource_name) { "My Test Board" }
13
+ let(:options) { {} }
14
+
15
+ before { @board = Fabricate(:board) }
16
+ after { database_cleanup }
17
+
18
+ describe ".initialize" do
19
+ subject { described_class.new(resource, options) }
20
+
21
+ it "assigns the resource to an instance variable" do
22
+ subject.instance_variable_get("@resource").must_equal(resource)
23
+ end
24
+
25
+ it "assigns the options to an instance variable" do
26
+ subject.instance_variable_get("@options").must_equal(options)
27
+ end
28
+ end
29
+
30
+ describe "#persist" do
31
+ subject { described_class.for(resource, options) }
32
+
33
+ context "when there is already a local copy" do
34
+ context "and the local copy is identical" do
35
+ it "returns the local copy" do
36
+ subject.must_equal(@board)
37
+ end
38
+ end
39
+
40
+ context "and the local copy is out of date" do
41
+ let(:resource_name) { "My Renamed Board" }
42
+
43
+ it "updates and returns the new local copy" do
44
+ subject.name.must_equal(resource_name)
45
+ end
46
+ end
47
+ end
48
+
49
+ context "when there is not already a local copy" do
50
+ let(:resource_name) { "My New Test Board" }
51
+
52
+ before { database_cleanup }
53
+
54
+ it "creates and returns the new local copy" do
55
+ subject.name.must_equal(resource_name)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,93 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ module Troo
4
+ describe BoardRetrieval do
5
+ let(:described_class) { BoardRetrieval }
6
+ let(:default) { true }
7
+ let(:board_name) { "My Test Board" }
8
+
9
+ before { @board = Fabricate(:board, default: default, name: board_name) }
10
+ after { database_cleanup }
11
+
12
+ describe ".all" do
13
+ subject { described_class.all }
14
+
15
+ it "retrieves all locally stored lists" do
16
+ subject.size.must_equal 1
17
+ end
18
+ end
19
+
20
+ describe ".default" do
21
+ subject { described_class.default }
22
+
23
+ context "when default is set" do
24
+ it "returns the default" do
25
+ subject.must_equal @board
26
+ end
27
+ end
28
+
29
+ context "when default is not set" do
30
+ let(:default) { false }
31
+
32
+ it { subject.must_equal(nil) }
33
+ end
34
+ end
35
+
36
+ describe ".retrieve" do
37
+ context "without an ID" do
38
+ subject { described_class.retrieve }
39
+
40
+ context "when default is set" do
41
+ it "returns the default" do
42
+ subject.must_equal @board
43
+ end
44
+ end
45
+
46
+ context "when default is not set" do
47
+ let(:default) { false }
48
+
49
+ it { subject.must_equal(nil) }
50
+ end
51
+ end
52
+
53
+ context "with an ID" do
54
+ subject { described_class.retrieve(id) }
55
+
56
+ context "local retrieval by database ID" do
57
+ let(:id) { @board.id }
58
+
59
+ it "returns the correct board" do
60
+ subject.name.must_equal("My Test Board")
61
+ end
62
+ end
63
+
64
+ context "local retrieval by external ID" do
65
+ let(:id) { "526d8e130a14a9d846001d96" }
66
+
67
+ it "returns the correct board" do
68
+ subject.name.must_equal("My Test Board")
69
+ end
70
+ end
71
+
72
+ context "remote retrieval by either ID" do
73
+ let(:id) { "526d_remote_board_005259" }
74
+ let(:board_name) { "My Remote Test Board" }
75
+
76
+ before { External::Board.stubs(:fetch).returns([@board]) }
77
+
78
+ it "returns the correct board" do
79
+ subject.name.must_equal("My Remote Test Board")
80
+ end
81
+ end
82
+
83
+ context "when the ID cannot be found" do
84
+ let(:id) { "not_found_id" }
85
+
86
+ before { External::Board.stubs(:fetch).returns([]) }
87
+
88
+ it { subject.must_equal(nil) }
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end