gradesfirst 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +2 -6
- data/gradesfirst.gemspec +2 -2
- data/lib/gradesfirst.rb +1 -0
- data/lib/gradesfirst/cli.rb +7 -29
- data/lib/gradesfirst/cli_helper.rb +33 -0
- data/lib/gradesfirst/command.rb +7 -0
- data/lib/gradesfirst/commit_message_command.rb +1 -1
- data/lib/gradesfirst/task_add_command.rb +51 -0
- data/lib/gradesfirst/task_cli.rb +48 -0
- data/lib/gradesfirst/task_command.rb +38 -30
- data/lib/gradesfirst/task_delete_command.rb +64 -0
- data/lib/gradesfirst/task_list_command.rb +40 -0
- data/lib/gradesfirst/task_move_command.rb +64 -0
- data/lib/gradesfirst/task_toggle_command.rb +65 -0
- data/lib/http_magic.rb +2 -258
- data/lib/http_magic/api.rb +233 -0
- data/lib/http_magic/request.rb +93 -0
- data/lib/http_magic/uri.rb +74 -0
- data/lib/pivotal_tracker.rb +1 -1
- data/test/branch_command_test.rb +8 -21
- data/test/cli_test.rb +51 -34
- data/test/command_test.rb +5 -7
- data/test/commit_message_command_test.rb +37 -45
- data/test/fixtures/task.json +10 -0
- data/test/fixtures/task_added.txt +6 -0
- data/test/fixtures/task_deleted.txt +6 -0
- data/test/fixtures/task_moved.txt +6 -0
- data/test/fixtures/task_toggled.txt +6 -0
- data/test/fixtures/tasks.txt +2 -2
- data/test/http_magic/{get_test.rb → api/get_test.rb} +1 -1
- data/test/http_magic/api/post_test.rb +34 -0
- data/test/http_magic/request_test.rb +63 -0
- data/test/http_magic/uri_test.rb +28 -55
- data/test/support/pivotal_test_helper.rb +110 -0
- data/test/support/request_expectation.rb +33 -0
- data/test/task_add_command_test.rb +54 -0
- data/test/task_delete_command_test.rb +57 -0
- data/test/task_list_command_test.rb +18 -0
- data/test/task_move_command_test.rb +66 -0
- data/test/task_toggle_command_test.rb +58 -0
- data/test/test_helper.rb +35 -19
- metadata +29 -7
- data/test/pivotal_tracker_test.rb +0 -46
- data/test/task_command_test.rb +0 -52
data/test/fixtures/tasks.txt
CHANGED
@@ -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
|
data/test/http_magic/uri_test.rb
CHANGED
@@ -1,76 +1,49 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'http_magic'
|
2
|
+
require 'http_magic/uri'
|
3
3
|
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
describe 'HttpMagic#uri' do
|
4
|
+
describe 'HttpMagic::Uri' do
|
8
5
|
before do
|
9
|
-
@
|
10
|
-
|
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 '
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
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 '
|
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
|
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
|
49
|
-
|
50
|
-
|
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
|
56
|
-
|
57
|
-
|
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
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|