trajectory 0.1.0

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 (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: