trajectory 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +6 -0
  6. data/Gemfile +19 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +57 -0
  9. data/Rakefile +18 -0
  10. data/config/env.yml +3 -0
  11. data/lib/trajectory/client.rb +24 -0
  12. data/lib/trajectory/core_ext/hash.rb +8 -0
  13. data/lib/trajectory/core_ext.rb +1 -0
  14. data/lib/trajectory/data_access/api.rb +54 -0
  15. data/lib/trajectory/data_access/data_store.rb +70 -0
  16. data/lib/trajectory/data_access.rb +2 -0
  17. data/lib/trajectory/domain/idea.rb +70 -0
  18. data/lib/trajectory/domain/ideas.rb +23 -0
  19. data/lib/trajectory/domain/iteration.rb +85 -0
  20. data/lib/trajectory/domain/iterations.rb +46 -0
  21. data/lib/trajectory/domain/project.rb +168 -0
  22. data/lib/trajectory/domain/projects.rb +55 -0
  23. data/lib/trajectory/domain/stories.rb +56 -0
  24. data/lib/trajectory/domain/story.rb +119 -0
  25. data/lib/trajectory/domain/update.rb +17 -0
  26. data/lib/trajectory/domain/user.rb +28 -0
  27. data/lib/trajectory/domain/users.rb +30 -0
  28. data/lib/trajectory/domain.rb +11 -0
  29. data/lib/trajectory/exceptions/bad_environment_error.rb +7 -0
  30. data/lib/trajectory/exceptions/missing_attribute_error.rb +12 -0
  31. data/lib/trajectory/exceptions/velocity_equal_to_zero_error.rb +11 -0
  32. data/lib/trajectory/exceptions.rb +3 -0
  33. data/lib/trajectory/version.rb +3 -0
  34. data/lib/trajectory.rb +15 -0
  35. data/spec/fabricators/iteration_fabricator.rb +18 -0
  36. data/spec/fabricators/project_fabricator.rb +11 -0
  37. data/spec/fabricators/story_fabricator.rb +18 -0
  38. data/spec/fixtures/vcr_cassettes/client.yml +853 -0
  39. data/spec/fixtures/vcr_cassettes/projects_and_ideas.yml +98 -0
  40. data/spec/fixtures/vcr_cassettes/projects_and_ideas_association.yml +52 -0
  41. data/spec/fixtures/vcr_cassettes/projects_and_iterations.yml +49 -0
  42. data/spec/fixtures/vcr_cassettes/projects_and_iterations_association.yml +49 -0
  43. data/spec/fixtures/vcr_cassettes/projects_and_stories.yml +101 -0
  44. data/spec/fixtures/vcr_cassettes/projects_and_stories_association.yml +147 -0
  45. data/spec/integration/client_spec.rb +96 -0
  46. data/spec/spec_helper.rb +13 -0
  47. data/spec/support/env.rb +11 -0
  48. data/spec/support/fabrication.rb +1 -0
  49. data/spec/support/simple_cov.rb +11 -0
  50. data/spec/support/timecop.rb +1 -0
  51. data/spec/support/vcr.rb +8 -0
  52. data/spec/unit/client_spec.rb +27 -0
  53. data/spec/unit/core_ext/hash_spec.rb +11 -0
  54. data/spec/unit/data_access/api_spec.rb +100 -0
  55. data/spec/unit/data_access/data_store_spec.rb +86 -0
  56. data/spec/unit/domain/idea_spec.rb +46 -0
  57. data/spec/unit/domain/ideas_spec.rb +22 -0
  58. data/spec/unit/domain/iteration_spec.rb +51 -0
  59. data/spec/unit/domain/iterations_spec.rb +47 -0
  60. data/spec/unit/domain/project_spec.rb +163 -0
  61. data/spec/unit/domain/projects_spec.rb +84 -0
  62. data/spec/unit/domain/stories_spec.rb +84 -0
  63. data/spec/unit/domain/story_spec.rb +71 -0
  64. data/spec/unit/domain/user_spec.rb +29 -0
  65. data/spec/unit/domain/users_spec.rb +36 -0
  66. data/spec/unit/exceptions/bad_environment_error_spec.rb +9 -0
  67. data/spec/unit/exceptions/missing_attribute_error_spec.rb +10 -0
  68. data/spec/unit/exceptions/velocity_equal_to_zero_error_spec.rb +10 -0
  69. data/trajectory.gemspec +21 -0
  70. metadata +174 -0
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe Stories do
5
+ it 'can be initialized from json attributes of its components' do
6
+ project = double(:project, :id => 4567)
7
+ json_stories_collection = [{'id' => 1234, 'title' => 'foo'}, {'id' => 42, 'title' => 'bar'}]
8
+
9
+ stories = Stories.from_json(project, json_stories_collection)
10
+
11
+ stories.should be_kind_of(Stories)
12
+ stories.first.id.should == 1234
13
+ stories.first.title.should == 'foo'
14
+
15
+ stories[1].id.should == 42
16
+ stories[1].title.should == 'bar'
17
+
18
+ stories.first.project_id.should == 4567
19
+ stories[1].project_id.should == 4567
20
+ end
21
+
22
+ it 'can filter started stories' do
23
+ story_1 = double(:started? => true)
24
+ story_2 = double(:started? => true)
25
+ story_3 = double(:started? => true)
26
+ stories = Stories.new(double(:started? => false),
27
+ story_1,
28
+ double(:started? => false),
29
+ double(:started? => false),
30
+ story_2,
31
+ story_3,
32
+ double(:started? => false))
33
+
34
+ stories.started.should == Stories.new(story_1, story_2, story_3)
35
+ end
36
+
37
+ it 'can filter unstarted stories' do
38
+ story_1 = double(:unstarted? => true)
39
+ story_2 = double(:unstarted? => true)
40
+ story_3 = double(:unstarted? => true)
41
+ stories = Stories.new(double(:unstarted? => false),
42
+ story_1,
43
+ double(:unstarted? => false),
44
+ double(:unstarted? => false),
45
+ story_2,
46
+ story_3,
47
+ double(:unstarted? => false))
48
+
49
+ stories.unstarted.should == Stories.new(story_1, story_2, story_3)
50
+ end
51
+
52
+ it 'can filter not completed stories' do
53
+ story_1 = double(:completed? => false)
54
+ story_2 = double(:completed? => false)
55
+ story_3 = double(:completed? => false)
56
+ stories = Stories.new(double(:completed? => true),
57
+ story_1,
58
+ double(:completed? => true),
59
+ double(:completed? => true),
60
+ story_2,
61
+ story_3,
62
+ double(:completed? => true))
63
+
64
+ stories.not_completed.should == Stories.new(story_1, story_2, story_3)
65
+ end
66
+
67
+ it 'can filter stories of a given iteration' do
68
+ iteration = double(:id => 12)
69
+
70
+ story_1 = double(:in_iteration? => true)
71
+ story_2 = double(:in_iteration? => true)
72
+ story_3 = double(:in_iteration? => true)
73
+ stories = Stories.new(double(:in_iteration? => false),
74
+ story_1,
75
+ double(:in_iteration? => false),
76
+ double(:in_iteration? => false),
77
+ story_2,
78
+ story_3,
79
+ double(:in_iteration? => false))
80
+
81
+ stories.in_iteration(iteration).should == Stories.new(story_1, story_2, story_3)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe Story do
5
+ let(:story) { Story.new(id: 42, title: 'foo') }
6
+
7
+ it 'can be initialized with named parameters' do
8
+ story.id.should == 42
9
+ story.title.should == 'foo'
10
+ end
11
+
12
+ it 'requires an id attribute' do
13
+ expect do
14
+ Story.new.id
15
+ end.to raise_error(MissingAttributeError)
16
+ end
17
+
18
+ it 'is the same story when ids are the same' do
19
+ story.should == Story.new(id: 42, title: 'bar')
20
+ end
21
+
22
+ context 'it has attributes accessors' do
23
+ %w(assignee_name task_type position created_at state_events title design_needed? updated_at idea_subject archived? points id development_needed? deleted? user_name comments_count state).each do |attribute|
24
+ it "'#{attribute}' accessor" do
25
+ Story.new.should respond_to(attribute.to_sym)
26
+ end
27
+ end
28
+ end
29
+
30
+ it 'delegates project fetching to data store' do
31
+ DataStore.should_receive(:find_project_by_id)
32
+
33
+ Story.new.project
34
+ end
35
+
36
+ it 'knows when it is started' do
37
+ Story.new(state: :started).should be_started
38
+ Story.new(state: :unstarted).should_not be_started
39
+ end
40
+
41
+ it 'knows when it is unstarted' do
42
+ Story.new(state: :unstarted).should be_unstarted
43
+ Story.new(state: :started).should_not be_unstarted
44
+ end
45
+
46
+ it 'knows when a story is not completed' do
47
+ %w(started unstarted delivered rejected).each do |state|
48
+ Story.new(state: state).should be_not_completed
49
+ Story.new(state: state).should_not be_completed
50
+ end
51
+ Story.new(state: :accepted).should_not be_not_completed
52
+ Story.new(state: :accepted).should be_completed
53
+ end
54
+
55
+ it 'knows if it is included in an iteration' do
56
+ iteration = double(:id => 42)
57
+ Story.new(iteration_id: 42).should be_in_iteration(iteration)
58
+ Story.new(iteration_id: 51).should_not be_in_iteration(iteration)
59
+ end
60
+
61
+ it 'delegates user fetching to data store' do
62
+ project = double
63
+ story = Story.new(user_id: 42)
64
+ story.stub(:project).and_return(project)
65
+
66
+ DataStore.should_receive(:find_user_of_project_with_id).with(project, 42)
67
+
68
+ story.user
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe User do
5
+ let(:idea) { User.new(id: 42, name: 'foo') }
6
+
7
+ it 'can be initialized with named parameters' do
8
+ idea.id.should == 42
9
+ end
10
+
11
+ it 'requires an id attribute' do
12
+ expect do
13
+ User.new.id
14
+ end.to raise_error(MissingAttributeError)
15
+ end
16
+
17
+ it 'is the same idea when ids are the same' do
18
+ idea.should == User.new(id: 42, name: 'bar')
19
+ end
20
+
21
+ context 'it has attributes accessors' do
22
+ %w(id name updated_at created_at gravatar_url email).each do |attribute|
23
+ it "'#{attribute}' accessor" do
24
+ User.new.should respond_to(attribute.to_sym)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe Users do
5
+ it 'can be initialize from an array of JSON attributes of its components' do
6
+ json_users_collection = [{'id' => 1234, 'email' => 'foo@exemple.com'}, {'id' => 42, 'email' => 'bar@exemple.com'}]
7
+
8
+ users = Users.from_json(json_users_collection)
9
+
10
+ users.should be_kind_of(Users)
11
+ users.first.id.should == 1234
12
+ users.first.email.should == 'foo@exemple.com'
13
+
14
+ users[1].id.should == 42
15
+ users[1].email.should == 'bar@exemple.com'
16
+ end
17
+
18
+ it 'can find a project by id' do
19
+ user = double(:user, id: 1234)
20
+ users = Users.new(double(:project, id: 1),
21
+ double(:user, id: 2),
22
+ user,
23
+ double(:user, id: 3))
24
+
25
+ users.find_by_id(1234).should == user
26
+ end
27
+
28
+ it "returns false when it can't find a user by id" do
29
+ users = Users.new(double(:user, id: 1),
30
+ double(:user, id: 2),
31
+ double(:user, id: 3))
32
+
33
+ users.find_by_id(1234).should == false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe BadEvnrionmentError do
5
+ it 'tell to the user to set environment variables' do
6
+ BadEvnrionmentError.new.to_s.should == "Specify trajectory API environment variables : TRAJECTORY_API_KEY and TRAJECTORY_ACCOUNT_KEYWORD"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe MissingAttributeError do
5
+ it 'is able to display an error message when given attribute is nil in given object' do
6
+ object = Object.new
7
+ MissingAttributeError.new(object, :some_nil_attribute).to_s.should == "Attribute #{:some_nil_attribute} of #{object.inspect} is nil."
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ module Trajectory
4
+ describe VelocityEqualToZeroError do
5
+ it 'can displays that velocity of a project is equal to zero' do
6
+ project = double
7
+ VelocityEqualToZeroError.new(project).to_s.should == "Estimated velocity of #{project.inspect} is equal to 0."
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'trajectory/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "trajectory"
8
+ gem.version = Trajectory::VERSION
9
+ gem.authors = ["Loïc Minaudier"]
10
+ gem.email = ["loic.minaudier@gmail.com"]
11
+ gem.description = %q{Ruby API Wrapper for Thoughbot Trajectory app}
12
+ gem.summary = %q{Ruby API Wrapper for Thoughbot Trajectory app}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_runtime_dependency 'virtus'
20
+ gem.add_runtime_dependency 'httparty'
21
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trajectory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Loïc Minaudier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: virtus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Ruby API Wrapper for Thoughbot Trajectory app
42
+ email:
43
+ - loic.minaudier@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .rspec
50
+ - .ruby-version
51
+ - .travis.yml
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - config/env.yml
57
+ - lib/trajectory.rb
58
+ - lib/trajectory/client.rb
59
+ - lib/trajectory/core_ext.rb
60
+ - lib/trajectory/core_ext/hash.rb
61
+ - lib/trajectory/data_access.rb
62
+ - lib/trajectory/data_access/api.rb
63
+ - lib/trajectory/data_access/data_store.rb
64
+ - lib/trajectory/domain.rb
65
+ - lib/trajectory/domain/idea.rb
66
+ - lib/trajectory/domain/ideas.rb
67
+ - lib/trajectory/domain/iteration.rb
68
+ - lib/trajectory/domain/iterations.rb
69
+ - lib/trajectory/domain/project.rb
70
+ - lib/trajectory/domain/projects.rb
71
+ - lib/trajectory/domain/stories.rb
72
+ - lib/trajectory/domain/story.rb
73
+ - lib/trajectory/domain/update.rb
74
+ - lib/trajectory/domain/user.rb
75
+ - lib/trajectory/domain/users.rb
76
+ - lib/trajectory/exceptions.rb
77
+ - lib/trajectory/exceptions/bad_environment_error.rb
78
+ - lib/trajectory/exceptions/missing_attribute_error.rb
79
+ - lib/trajectory/exceptions/velocity_equal_to_zero_error.rb
80
+ - lib/trajectory/version.rb
81
+ - spec/fabricators/iteration_fabricator.rb
82
+ - spec/fabricators/project_fabricator.rb
83
+ - spec/fabricators/story_fabricator.rb
84
+ - spec/fixtures/vcr_cassettes/client.yml
85
+ - spec/fixtures/vcr_cassettes/projects_and_ideas.yml
86
+ - spec/fixtures/vcr_cassettes/projects_and_ideas_association.yml
87
+ - spec/fixtures/vcr_cassettes/projects_and_iterations.yml
88
+ - spec/fixtures/vcr_cassettes/projects_and_iterations_association.yml
89
+ - spec/fixtures/vcr_cassettes/projects_and_stories.yml
90
+ - spec/fixtures/vcr_cassettes/projects_and_stories_association.yml
91
+ - spec/integration/client_spec.rb
92
+ - spec/spec_helper.rb
93
+ - spec/support/env.rb
94
+ - spec/support/fabrication.rb
95
+ - spec/support/simple_cov.rb
96
+ - spec/support/timecop.rb
97
+ - spec/support/vcr.rb
98
+ - spec/unit/client_spec.rb
99
+ - spec/unit/core_ext/hash_spec.rb
100
+ - spec/unit/data_access/api_spec.rb
101
+ - spec/unit/data_access/data_store_spec.rb
102
+ - spec/unit/domain/idea_spec.rb
103
+ - spec/unit/domain/ideas_spec.rb
104
+ - spec/unit/domain/iteration_spec.rb
105
+ - spec/unit/domain/iterations_spec.rb
106
+ - spec/unit/domain/project_spec.rb
107
+ - spec/unit/domain/projects_spec.rb
108
+ - spec/unit/domain/stories_spec.rb
109
+ - spec/unit/domain/story_spec.rb
110
+ - spec/unit/domain/user_spec.rb
111
+ - spec/unit/domain/users_spec.rb
112
+ - spec/unit/exceptions/bad_environment_error_spec.rb
113
+ - spec/unit/exceptions/missing_attribute_error_spec.rb
114
+ - spec/unit/exceptions/velocity_equal_to_zero_error_spec.rb
115
+ - trajectory.gemspec
116
+ homepage: ''
117
+ licenses: []
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.0.0
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Ruby API Wrapper for Thoughbot Trajectory app
139
+ test_files:
140
+ - spec/fabricators/iteration_fabricator.rb
141
+ - spec/fabricators/project_fabricator.rb
142
+ - spec/fabricators/story_fabricator.rb
143
+ - spec/fixtures/vcr_cassettes/client.yml
144
+ - spec/fixtures/vcr_cassettes/projects_and_ideas.yml
145
+ - spec/fixtures/vcr_cassettes/projects_and_ideas_association.yml
146
+ - spec/fixtures/vcr_cassettes/projects_and_iterations.yml
147
+ - spec/fixtures/vcr_cassettes/projects_and_iterations_association.yml
148
+ - spec/fixtures/vcr_cassettes/projects_and_stories.yml
149
+ - spec/fixtures/vcr_cassettes/projects_and_stories_association.yml
150
+ - spec/integration/client_spec.rb
151
+ - spec/spec_helper.rb
152
+ - spec/support/env.rb
153
+ - spec/support/fabrication.rb
154
+ - spec/support/simple_cov.rb
155
+ - spec/support/timecop.rb
156
+ - spec/support/vcr.rb
157
+ - spec/unit/client_spec.rb
158
+ - spec/unit/core_ext/hash_spec.rb
159
+ - spec/unit/data_access/api_spec.rb
160
+ - spec/unit/data_access/data_store_spec.rb
161
+ - spec/unit/domain/idea_spec.rb
162
+ - spec/unit/domain/ideas_spec.rb
163
+ - spec/unit/domain/iteration_spec.rb
164
+ - spec/unit/domain/iterations_spec.rb
165
+ - spec/unit/domain/project_spec.rb
166
+ - spec/unit/domain/projects_spec.rb
167
+ - spec/unit/domain/stories_spec.rb
168
+ - spec/unit/domain/story_spec.rb
169
+ - spec/unit/domain/user_spec.rb
170
+ - spec/unit/domain/users_spec.rb
171
+ - spec/unit/exceptions/bad_environment_error_spec.rb
172
+ - spec/unit/exceptions/missing_attribute_error_spec.rb
173
+ - spec/unit/exceptions/velocity_equal_to_zero_error_spec.rb
174
+ has_rdoc: