gradesfirst 0.2.1 → 0.3.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 (46) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +1 -2
  3. data/Gemfile.lock +2 -6
  4. data/gradesfirst.gemspec +2 -2
  5. data/lib/gradesfirst.rb +1 -0
  6. data/lib/gradesfirst/cli.rb +7 -29
  7. data/lib/gradesfirst/cli_helper.rb +33 -0
  8. data/lib/gradesfirst/command.rb +7 -0
  9. data/lib/gradesfirst/commit_message_command.rb +1 -1
  10. data/lib/gradesfirst/task_add_command.rb +51 -0
  11. data/lib/gradesfirst/task_cli.rb +48 -0
  12. data/lib/gradesfirst/task_command.rb +38 -30
  13. data/lib/gradesfirst/task_delete_command.rb +64 -0
  14. data/lib/gradesfirst/task_list_command.rb +40 -0
  15. data/lib/gradesfirst/task_move_command.rb +64 -0
  16. data/lib/gradesfirst/task_toggle_command.rb +65 -0
  17. data/lib/http_magic.rb +2 -258
  18. data/lib/http_magic/api.rb +233 -0
  19. data/lib/http_magic/request.rb +93 -0
  20. data/lib/http_magic/uri.rb +74 -0
  21. data/lib/pivotal_tracker.rb +1 -1
  22. data/test/branch_command_test.rb +8 -21
  23. data/test/cli_test.rb +51 -34
  24. data/test/command_test.rb +5 -7
  25. data/test/commit_message_command_test.rb +37 -45
  26. data/test/fixtures/task.json +10 -0
  27. data/test/fixtures/task_added.txt +6 -0
  28. data/test/fixtures/task_deleted.txt +6 -0
  29. data/test/fixtures/task_moved.txt +6 -0
  30. data/test/fixtures/task_toggled.txt +6 -0
  31. data/test/fixtures/tasks.txt +2 -2
  32. data/test/http_magic/{get_test.rb → api/get_test.rb} +1 -1
  33. data/test/http_magic/api/post_test.rb +34 -0
  34. data/test/http_magic/request_test.rb +63 -0
  35. data/test/http_magic/uri_test.rb +28 -55
  36. data/test/support/pivotal_test_helper.rb +110 -0
  37. data/test/support/request_expectation.rb +33 -0
  38. data/test/task_add_command_test.rb +54 -0
  39. data/test/task_delete_command_test.rb +57 -0
  40. data/test/task_list_command_test.rb +18 -0
  41. data/test/task_move_command_test.rb +66 -0
  42. data/test/task_toggle_command_test.rb +58 -0
  43. data/test/test_helper.rb +35 -19
  44. metadata +29 -7
  45. data/test/pivotal_tracker_test.rb +0 -46
  46. data/test/task_command_test.rb +0 -52
@@ -0,0 +1,6 @@
1
+ Task was successfully added.
2
+
3
+ Bring me the passengers (http://www.pivotaltracker.com/story/show/29384793)
4
+
5
+ 1. [X] Port 0
6
+ 2. [ ] Port 90
@@ -0,0 +1,6 @@
1
+ Task was successfully deleted.
2
+
3
+ Bring me the passengers (http://www.pivotaltracker.com/story/show/29384793)
4
+
5
+ 1. [X] Port 0
6
+ 2. [ ] Port 90
@@ -0,0 +1,6 @@
1
+ Task was successfully moved.
2
+
3
+ Bring me the passengers (http://www.pivotaltracker.com/story/show/29384793)
4
+
5
+ 1. [X] Port 0
6
+ 2. [ ] Port 90
@@ -0,0 +1,6 @@
1
+ Task completion status was successfully toggled.
2
+
3
+ Bring me the passengers (http://www.pivotaltracker.com/story/show/29384793)
4
+
5
+ 1. [X] Port 0
6
+ 2. [ ] Port 90
@@ -1,4 +1,4 @@
1
1
  Bring me the passengers (http://www.pivotaltracker.com/story/show/29384793)
2
2
 
3
- [X] Port 0
4
- [ ] Port 90
3
+ 1. [X] Port 0
4
+ 2. [ ] Port 90
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
  require 'http_magic'
3
3
 
4
- class HttpMagicTest < HttpMagic
4
+ class HttpMagicTest < HttpMagic::Api
5
5
  end
6
6
 
7
7
  describe 'HttpMagic#get' do
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+ require 'http_magic'
3
+
4
+ class HttpMagicTest < HttpMagic::Api
5
+ end
6
+
7
+ describe 'HttpMagic#post' do
8
+ before do
9
+ @url = HttpMagicTest.url 'www.example.com'
10
+ HttpMagicTest.namespace nil
11
+ HttpMagicTest.headers nil
12
+ end
13
+
14
+ it 'should send POST request' do
15
+ stub_post = stub_request(:post, "https://#{@url}")
16
+
17
+ HttpMagicTest.post
18
+ assert_requested stub_post
19
+ end
20
+
21
+ it 'should send data with POST request' do
22
+ expected_data = {
23
+ apple: 'sauce',
24
+ banana: 'bread'
25
+ }
26
+ stub_post = stub_request(:post, "https://#{@url}/foo").with(
27
+ body: expected_data
28
+ )
29
+
30
+ HttpMagicTest.foo.post(expected_data)
31
+
32
+ assert_requested stub_post
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+ require 'http_magic/uri'
3
+ require 'http_magic/request'
4
+
5
+ describe 'HttpMagic::Request' do
6
+ before do
7
+ @domain = 'example.com'
8
+ @uri = HttpMagic::Uri.new(@domain)
9
+ end
10
+
11
+ it 'should make a request' do
12
+ stub_request = stub_request(
13
+ :get,
14
+ "https://#{@domain}/api/v2/path/to/something"
15
+ )
16
+
17
+ @uri.namespace = 'api/v2'
18
+ @uri.parts = ['path', 'to', 'something']
19
+ request = HttpMagic::Request.new(@uri)
20
+ request.get
21
+
22
+ assert_requested stub_request
23
+ end
24
+
25
+ it 'should return content on request' do
26
+ content = 'This is SPARTA!'
27
+ stub_request(:get, "https://#{@domain}").
28
+ to_return(body: content)
29
+
30
+ request = HttpMagic::Request.new(@uri)
31
+
32
+ assert_equal content, request.get
33
+ end
34
+
35
+ it 'should be able to post data as hash' do
36
+ expected_data = {
37
+ apple: 'crispy',
38
+ banana: 'soft'
39
+ }
40
+ stub_request = stub_request(:post, "https://#{@domain}").with(
41
+ body: expected_data.to_json,
42
+ headers: { 'content-type' => 'application/json' }
43
+ )
44
+
45
+ request = HttpMagic::Request.new(@uri, data: expected_data)
46
+ request.post
47
+
48
+ assert_requested stub_request
49
+ end
50
+
51
+ it 'should set correct headers' do
52
+ stub_request = stub_request(:get, "https://#{@domain}").
53
+ with(headers: { 'X-AuthToken' => 'test_token' })
54
+
55
+ request = HttpMagic::Request.new(
56
+ @uri,
57
+ headers: { 'X-AuthToken' => 'test_token' }
58
+ )
59
+ request.get
60
+
61
+ assert_requested stub_request
62
+ end
63
+ end
@@ -1,76 +1,49 @@
1
1
  require 'test_helper'
2
- require 'http_magic'
2
+ require 'http_magic/uri'
3
3
 
4
- class HttpMagicTest < HttpMagic
5
- end
6
-
7
- describe 'HttpMagic#uri' do
4
+ describe 'HttpMagic::Uri' do
8
5
  before do
9
- @url = HttpMagicTest.url 'www.example.com'
10
- HttpMagicTest.namespace nil
11
- end
12
-
13
- it 'should make a good root uri' do
14
- assert_equal(
15
- "#{@url}/",
16
- HttpMagicTest.uri
17
- )
6
+ @domain = 'example.com'
7
+ @uri = uri = HttpMagic::Uri.new(@domain)
18
8
  end
19
9
 
20
- it 'should make a uri that begins with new' do
21
- assert_equal(
22
- "#{@url}/new",
23
- HttpMagicTest.new.uri
24
- )
10
+ it 'must have a domain param' do
11
+ assert_raises ArgumentError do
12
+ HttpMagic::Uri.new
13
+ end
25
14
  end
26
15
 
27
- it 'should make a good single part uri' do
28
- assert_equal(
29
- "#{@url}/foos",
30
- HttpMagicTest.foos.uri
31
- )
16
+ it 'should return the domain' do
17
+ assert_equal @domain, @uri.domain
32
18
  end
33
19
 
34
- it 'should make a good uri with an index' do
35
- assert_equal(
36
- "#{@url}/foos/99",
37
- HttpMagicTest.foos[99].uri
38
- )
20
+ it 'can build a simple uri' do
21
+ assert_equal "https://#{@domain}/", @uri.build
39
22
  end
40
23
 
41
- it 'should make a good nested uri' do
42
- assert_equal(
43
- "#{@url}/foos/99/bars",
44
- HttpMagicTest.foos[99].bars.uri
45
- )
24
+ it 'should have url' do
25
+ assert_equal "https://#{@domain}", @uri.url
46
26
  end
47
27
 
48
- it 'should make a uri including a keyword at the beginning' do
49
- assert_equal(
50
- "#{@url}/get",
51
- HttpMagicTest[:get].uri
52
- )
28
+ it 'should create urn with parts' do
29
+ @uri.parts = ['path', 'to', 'something']
30
+ assert_equal '/path/to/something', @uri.urn
53
31
  end
54
32
 
55
- it 'should make a uri including a keyword in the middle' do
56
- assert_equal(
57
- "#{@url}/foo/get/bar",
58
- HttpMagicTest.foo[:get].bar.uri
59
- )
33
+ it 'should create urn with namespace' do
34
+ @uri.namespace = 'api/v2'
35
+ assert_equal '/api/v2', @uri.urn
60
36
  end
61
37
 
62
- it 'should make a uri including a keyword at the end' do
63
- assert_equal(
64
- "#{@url}/foo/bar/get",
65
- HttpMagicTest.foo.bar[:get].uri
66
- )
38
+ it 'should create urn with namespace and parts combined' do
39
+ @uri.parts = ['path', 'to', 'something']
40
+ @uri.namespace = 'api/v2'
41
+ assert_equal '/api/v2/path/to/something', @uri.urn
67
42
  end
68
43
 
69
- it 'should make a namespaced uri' do
70
- HttpMagicTest.namespace 'api/v5'
71
- assert_equal(
72
- "#{@url}/api/v5/foo/bar/get",
73
- HttpMagicTest.foo.bar[:get].uri
74
- )
44
+ it 'should create the full uri with urn included' do
45
+ @uri.parts = ['path', 'to', 'something']
46
+ @uri.namespace = 'api/v2'
47
+ assert_equal "https://#{@domain}/api/v2/path/to/something", @uri.build
75
48
  end
76
49
  end
@@ -0,0 +1,110 @@
1
+ module GradesFirst
2
+ module PivotalTestHelper
3
+
4
+ def bar_story_id
5
+ '29384793'
6
+ end
7
+
8
+ def foo_story_id
9
+ '57348714'
10
+ end
11
+
12
+ def missing_story_id
13
+ '29384799'
14
+ end
15
+
16
+ def pivotal_tracker_setup
17
+ PivotalTracker.api_token = 'test_token'
18
+ end
19
+
20
+ def stub_bar_story_request
21
+ stub_pivotal_request(
22
+ :get,
23
+ 'stories/' + bar_story_id,
24
+ response: { body: fixture_file('story_bar.json') }
25
+ )
26
+ end
27
+
28
+ def stub_bar_story_tasks_request
29
+ stub_pivotal_request(
30
+ :get,
31
+ urn_for_bar_story_tasks,
32
+ response: { body: fixture_file('tasks.json') }
33
+ )
34
+ end
35
+
36
+ def stub_foo_story_request
37
+ stub_pivotal_request(
38
+ :get,
39
+ 'stories/' + foo_story_id,
40
+ response: { body: fixture_file('story_foo.json') }
41
+ )
42
+ end
43
+
44
+ def stub_missing_story_request
45
+ stub_pivotal_request(
46
+ :get,
47
+ 'stories/' + missing_story_id,
48
+ response: { status: 404 }
49
+ )
50
+ end
51
+
52
+ # Simplify and DRY up stubbing out of PivotalTracker requests.
53
+ def stub_pivotal_request(method, urn, options = {})
54
+ default_request = {
55
+ headers: { 'X-TrackerToken' => 'test_token' }
56
+ }
57
+ if method == :post
58
+ default_request[:headers]['Content-Type'] = 'application/json'
59
+ end
60
+ default_response = {
61
+ headers: { 'Content-Type' => 'application/json' },
62
+ body: '',
63
+ status: 200
64
+ }
65
+
66
+ uri = "https://www.pivotaltracker.com:443/services/v5/#{urn}"
67
+ stub_request(method, uri).
68
+ with(default_request.merge(options[:request] || {})).
69
+ to_return(default_response.merge(options[:response] || {}))
70
+
71
+ RequestExpectation.new(method, uri)
72
+ end
73
+
74
+ def urn_for_bar_story_tasks
75
+ "projects/10687/stories/#{bar_story_id}/tasks"
76
+ end
77
+
78
+ def urn_for_bar_story_task(task_id)
79
+ urn_for_bar_story_tasks + "/#{task_id}"
80
+ end
81
+
82
+ module ClassMethods
83
+
84
+ def specify_response_for_invalid_story(*args)
85
+ specify '#response responds with error message with an invalid story' do
86
+ expect_requests stub_missing_story_request do
87
+ @command.stub :current_branch, missing_story_id do
88
+ @command.execute(*args)
89
+ end
90
+ end
91
+ assert_equal @command.send(:story_error_message), @command.response
92
+ end
93
+ end
94
+
95
+ def specify_response_for_invalid_task_position(method, *args)
96
+ specify '#response when position does not exist' do
97
+ stub_bar_story_request
98
+ stub_bar_story_tasks_request
99
+ @command.stub :current_branch, bar_story_id do
100
+ @command.execute(*args)
101
+ end
102
+ assert_equal @command.send(:position_invalid_message), @command.response
103
+ assert_not_requested method, /.*/
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,33 @@
1
+ # This class encapsulates creating http request expectations with the webmock
2
+ # assert_requested assertion.
3
+ #
4
+ # Example:
5
+ # expectation = RequestExpectation(:get, 'http://example.com').times(2)
6
+ # assert_requested(*expectation.to_args)
7
+ class RequestExpectation
8
+ # Store the HTTP request method and uri that are expected and specifies the
9
+ # default number of times that the request is expected to made.
10
+ def initialize(method, uri)
11
+ @method = method
12
+ @uri = uri
13
+ @times = 1
14
+ end
15
+
16
+ # Specifies the number of times that a request is expected to be made.
17
+ #
18
+ # Example:
19
+ # RequestExpectation.new(:get, 'http://example.com').times(2).to_args
20
+ #
21
+ # Retuns an instance of itself to allow for method chaining.
22
+ def times(value)
23
+ @times = value
24
+ self
25
+ end
26
+
27
+ # Creates a set of method arguments for the Webmock assert_requested method.
28
+ #
29
+ # Returns an array of Webmock assert_request method arguments.
30
+ def to_args
31
+ [@method, @uri, { times: @times }]
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+ require 'gradesfirst/task_add_command'
3
+
4
+ describe GradesFirst::TaskAddCommand do
5
+ before do
6
+ @task_description = 'New task.'
7
+ @command = GradesFirst::TaskAddCommand.new
8
+ end
9
+
10
+ def stub_bar_story_task_add_request(response)
11
+ stub_pivotal_request(
12
+ :post,
13
+ urn_for_bar_story_tasks,
14
+ request: { body: "{\"description\":\"#{@task_description}\"}" },
15
+ response: response
16
+ )
17
+ end
18
+
19
+ def stub_failing_bar_story_task_add_request
20
+ stub_bar_story_task_add_request status: 500
21
+ end
22
+
23
+ def stub_working_bar_story_task_add_request
24
+ stub_bar_story_task_add_request body: fixture_file('task.json')
25
+ end
26
+
27
+ specify '#response responds with confirmation and task list' do
28
+ stubbed_requests = [
29
+ stub_bar_story_request,
30
+ stub_bar_story_tasks_request,
31
+ stub_working_bar_story_task_add_request
32
+ ]
33
+
34
+ response = nil
35
+ expect_requests stubbed_requests do
36
+ @command.stub :current_branch, bar_story_id do
37
+ @command.execute(@task_description)
38
+ end
39
+ response = @command.response
40
+ end
41
+ assert_equal fixture_file('task_added.txt'), response
42
+ end
43
+
44
+ specify '#response when adding the task fails' do
45
+ stub_bar_story_request
46
+ stub_failing_bar_story_task_add_request
47
+ @command.stub :current_branch, bar_story_id do
48
+ @command.execute(@task_description)
49
+ end
50
+ assert_equal @command.send(:task_error_message), @command.response
51
+ end
52
+
53
+ specify_response_for_invalid_story @task_description
54
+ end