pivo_flow 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/CHANGELOG.md +18 -0
- data/README.md +4 -37
- data/bin/pf-prepare-commit-msg +10 -4
- data/lib/pivo_flow/cli.rb +3 -8
- data/lib/pivo_flow/pivotal.rb +14 -10
- data/lib/pivo_flow/state.rb +23 -0
- data/lib/pivo_flow/version.rb +1 -1
- data/lib/pivo_flow.rb +1 -0
- data/pivo_flow.gemspec +0 -1
- data/spec/pivo_flow/base_spec.rb +18 -16
- data/spec/pivo_flow/cli_spec.rb +18 -35
- data/spec/pivo_flow/pivotal_spec.rb +67 -63
- data/spec/pivo_flow/state_spec.rb +38 -0
- data/spec/spec_helper.rb +19 -11
- metadata +7 -5
- data/.travis.yml +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b0e99ca7d80278c1cee9005ae3c938aa10da3e8
|
4
|
+
data.tar.gz: 1d37fb1d48975ec2f1374c6965c63e32cfe2b79b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fcc5cd5b21649c2ef9ae3e9157861f6f0beacf675a585c6353d7c0567ec2ac075cb5554505a7cc56519e1419cd58236d4b3d9a63c23d210348ce8dd6762e0ff
|
7
|
+
data.tar.gz: 28688a32e8c4af94d3ccf7d3dbc73c3782132b3a791d9816ab99e1bc9ae722f6075795650b78c0789fb3c72d04466eb7db4d9eabfe2c83b69d5e8a49d303e789
|
data/.rspec
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
# 0.7 - 2017-10-06
|
6
|
+
|
7
|
+
Thanks [David Balatero](https://github.com/dbalatero) for your help with this
|
8
|
+
release!
|
9
|
+
|
10
|
+
## Added
|
11
|
+
|
12
|
+
* [Ability to track story ID by branch](https://github.com/lubieniebieski/pivo_flow/pull/20)
|
13
|
+
|
14
|
+
## Fixed
|
15
|
+
|
16
|
+
* [Readme badges](https://github.com/lubieniebieski/pivo_flow/pull/21)
|
17
|
+
* [Commit message fixes](https://github.com/lubieniebieski/pivo_flow/pull/23)
|
18
|
+
* [Make branch names start with the name, downcased](https://github.com/lubieniebieski/pivo_flow/pull/22)
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# PivoFlow
|
2
2
|
|
3
|
-
[![
|
4
|
-
[![
|
3
|
+
[![](http://img.shields.io/codeclimate/github/lubieniebieski/pivo_flow.svg?style=flat-square)](https://codeclimate.com/github/lubieniebieski/pivo_flow)
|
4
|
+
[![](https://img.shields.io/circleci/project/github/lubieniebieski/pivo_flow.svg?style=flat-square)](https://circleci.com/gh/lubieniebieski/pivo_flow)
|
5
5
|
|
6
6
|
PivoFlow lets you choose the story you are currently working on from Pivotal Tracker. Intended for all the people, who doesn't like feature-branch approach or are "merdżuj - nie pier*ol"-theory enthusiasts.
|
7
7
|
|
@@ -61,42 +61,9 @@ Show current STORY_ID from temp file
|
|
61
61
|
|
62
62
|
This gem installs a `pepare-commit-msg` hook by adding a reference to `pf-prepare-commit-msg` file. In short: you shouldn't be worried about your own `prepare-commit-msg` hook, the one added by `pivo_flow` will be added in the last line of original hook file.
|
63
63
|
|
64
|
-
##
|
65
|
-
### 0.6 Current release
|
64
|
+
## Changelog
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
### 0.5
|
70
|
-
|
71
|
-
* set ticket id without connecting to pivotal with 'pf set NUMBER'
|
72
|
-
|
73
|
-
### 0.4
|
74
|
-
|
75
|
-
* colorized output
|
76
|
-
* **TODO** story statistics
|
77
|
-
* **TODO** git statistics (number of commits in some peroid, average, etc.)
|
78
|
-
|
79
|
-
### 0.3
|
80
|
-
|
81
|
-
* single-story view with comments and tasks
|
82
|
-
* flow:
|
83
|
-
* select story
|
84
|
-
* read the story description
|
85
|
-
* accept or back to story selection
|
86
|
-
* `pf info` displaying info about current task
|
87
|
-
* `pf deliver` ability to deliver finished stories [#6]
|
88
|
-
* options via `OptionParser`
|
89
|
-
|
90
|
-
### 0.2
|
91
|
-
|
92
|
-
* git hook
|
93
|
-
* formatted output
|
94
|
-
* bugfixes
|
95
|
-
|
96
|
-
### before 0.2
|
97
|
-
|
98
|
-
* gem basic structure
|
99
|
-
* git config read/write
|
66
|
+
See [CHANGELOG.md](https://github.com/lubieniebieski/pivo_flow/blob/master/CHANGELOG.md) file
|
100
67
|
|
101
68
|
## Contributing
|
102
69
|
|
data/bin/pf-prepare-commit-msg
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
branch_name = `git symbolic-ref HEAD 2>/dev/null | cut -d '/' -f3`.strip
|
4
|
+
story_path = "tmp/.pivo_flow/stories/#{branch_name}"
|
5
|
+
|
6
|
+
if !branch_name.empty? && File.exists?(story_path)
|
4
7
|
story_id = File.read(story_path).strip
|
8
|
+
|
5
9
|
if story_id =~ /(\d{7,})/
|
6
10
|
puts IO.read(ARGV[0])
|
7
11
|
commit_msg = IO.read(ARGV[0])
|
8
|
-
|
12
|
+
|
13
|
+
unless commit_msg.include?("##{$1}") or commit_msg =~ /Merge branch/
|
9
14
|
File.open(ARGV[0], 'w') do |file|
|
10
|
-
file.print commit_msg
|
15
|
+
file.print commit_msg.strip
|
16
|
+
file.print "\n\n"
|
11
17
|
file.print "[##{story_id}]"
|
12
18
|
end
|
13
19
|
end
|
data/lib/pivo_flow/cli.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module PivoFlow
|
2
2
|
class Cli
|
3
|
+
include PivoFlow::State
|
3
4
|
|
4
5
|
def initialize *args
|
5
|
-
@file_story_path = File.join(Dir.pwd, "/tmp/.pivotal_story_id")
|
6
6
|
@args = args
|
7
7
|
end
|
8
8
|
|
@@ -58,7 +58,7 @@ module PivoFlow
|
|
58
58
|
|
59
59
|
def clear
|
60
60
|
unless current_story_id.nil?
|
61
|
-
FileUtils.remove_file(
|
61
|
+
FileUtils.remove_file(current_story_id_file_path)
|
62
62
|
puts "Current pivotal story id cleared."
|
63
63
|
else
|
64
64
|
puts no_story_found_message
|
@@ -98,7 +98,7 @@ module PivoFlow
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def no_story_found_message
|
101
|
-
"No story found in #{
|
101
|
+
"No story found in #{current_story_id_file_path}"
|
102
102
|
end
|
103
103
|
|
104
104
|
def no_method_error
|
@@ -109,11 +109,6 @@ module PivoFlow
|
|
109
109
|
puts "Ups, no such method..."
|
110
110
|
end
|
111
111
|
|
112
|
-
def current_story_id
|
113
|
-
return nil unless File.exists?(@file_story_path)
|
114
|
-
File.open(@file_story_path).read.strip
|
115
|
-
end
|
116
|
-
|
117
112
|
def parse_argv(args)
|
118
113
|
@options = {}
|
119
114
|
|
data/lib/pivo_flow/pivotal.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
module PivoFlow
|
3
3
|
class Pivotal < Base
|
4
|
-
|
5
|
-
@story_id_file_name = ".pivotal_story_id"
|
6
|
-
@story_id_tmp_path = File.join(@current_dir, "/tmp")
|
7
|
-
@story_id_file_path = File.join(@story_id_tmp_path, @story_id_file_name)
|
4
|
+
include PivoFlow::State
|
8
5
|
|
6
|
+
def run
|
9
7
|
PivotalTracker::Client.token = @options["api-token"]
|
10
8
|
PivotalTracker::Client.use_ssl = true
|
11
9
|
end
|
@@ -228,15 +226,21 @@ module PivoFlow
|
|
228
226
|
|
229
227
|
def create_branch story_id
|
230
228
|
story = find_story(story_id)
|
229
|
+
|
231
230
|
if story.nil?
|
232
|
-
puts "Sorry, this story
|
231
|
+
puts "Sorry, this story could not be found (#{story_id})"
|
233
232
|
return
|
234
233
|
end
|
235
234
|
|
236
|
-
ticket_name = story.name
|
237
|
-
|
235
|
+
ticket_name = story.name
|
236
|
+
.tr('^A-Za-z0-9 ', '')
|
237
|
+
.tr(' ', '-')
|
238
|
+
.downcase
|
239
|
+
|
240
|
+
branch_name = [ticket_name, story.id].join("-")
|
238
241
|
|
239
242
|
git_create_branch(branch_name)
|
243
|
+
save_story_id_to_file(story_id)
|
240
244
|
end
|
241
245
|
|
242
246
|
def start_story story_id
|
@@ -252,12 +256,12 @@ module PivoFlow
|
|
252
256
|
end
|
253
257
|
|
254
258
|
def remove_story_id_file
|
255
|
-
FileUtils.remove_file(
|
259
|
+
FileUtils.remove_file(current_story_id_file_path)
|
256
260
|
end
|
257
261
|
|
258
262
|
def save_story_id_to_file story_id
|
259
|
-
FileUtils.mkdir_p(
|
260
|
-
File.open(
|
263
|
+
FileUtils.mkdir_p(story_id_tmp_path)
|
264
|
+
File.open(current_story_id_file_path, 'w') { |f| f.write(story_id) }
|
261
265
|
end
|
262
266
|
|
263
267
|
def show_stories count=9
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PivoFlow
|
2
|
+
module State
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def current_branch_name
|
6
|
+
Grit::Repo.new(Dir.pwd).head.name
|
7
|
+
end
|
8
|
+
|
9
|
+
def story_id_tmp_path
|
10
|
+
"#{Dir.pwd}/tmp/.pivo_flow/stories"
|
11
|
+
end
|
12
|
+
|
13
|
+
def current_story_id_file_path
|
14
|
+
File.join(story_id_tmp_path, current_branch_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_story_id
|
18
|
+
return nil unless File.exist?(current_story_id_file_path)
|
19
|
+
|
20
|
+
File.read(current_story_id_file_path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/pivo_flow/version.rb
CHANGED
data/lib/pivo_flow.rb
CHANGED
data/pivo_flow.gemspec
CHANGED
data/spec/pivo_flow/base_spec.rb
CHANGED
@@ -1,23 +1,27 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require_relative './../../lib/pivo_flow/errors'
|
3
|
-
describe PivoFlow::Base do
|
4
3
|
|
4
|
+
describe PivoFlow::Base do
|
5
5
|
let(:base) { PivoFlow::Base.new }
|
6
6
|
|
7
7
|
before do
|
8
|
-
PivoFlow::Base.
|
8
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:puts)
|
9
|
+
|
9
10
|
stub_git_config
|
10
11
|
stub_base_methods(PivoFlow::Base)
|
11
12
|
end
|
12
13
|
|
13
14
|
it "raises exception if it's outside of git repo" do
|
14
|
-
PivoFlow::Base.
|
15
|
-
|
15
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:git_directory_present?)
|
16
|
+
.and_return(false)
|
17
|
+
|
18
|
+
expect{ base }.to raise_error(PivoFlow::Errors::NoGitRepoFound)
|
16
19
|
end
|
17
20
|
|
18
21
|
it "calls hook installation if it's needed" do
|
19
|
-
PivoFlow::Base.
|
20
|
-
PivoFlow::Base.
|
22
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:git_hook_needed?).and_return(true)
|
23
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:install_git_hook)
|
24
|
+
|
21
25
|
base
|
22
26
|
end
|
23
27
|
|
@@ -33,13 +37,13 @@ describe PivoFlow::Base do
|
|
33
37
|
|
34
38
|
it "creates an executable prepare-commit-msg file" do
|
35
39
|
base.install_git_hook
|
36
|
-
File.executable?(file_name).
|
40
|
+
expect(File.executable?(file_name)).to be_truthy
|
37
41
|
end
|
38
42
|
|
39
43
|
it "creates an executable pf-prepare-commit-msg file" do
|
40
44
|
File.delete pf_file_name if File.exists? pf_file_name
|
41
45
|
base.install_git_hook
|
42
|
-
File.executable?(pf_file_name).
|
46
|
+
expect(File.executable?(pf_file_name)).to be_truthy
|
43
47
|
end
|
44
48
|
|
45
49
|
end
|
@@ -47,15 +51,15 @@ describe PivoFlow::Base do
|
|
47
51
|
describe "parses git config" do
|
48
52
|
|
49
53
|
it "and returns project id" do
|
50
|
-
base.options["project-id"].
|
54
|
+
expect(base.options["project-id"]).to eq "123456"
|
51
55
|
end
|
52
56
|
|
53
57
|
it "and returns api token" do
|
54
|
-
base.options["api-token"].
|
58
|
+
expect(base.options["api-token"]).to eq "testtesttesttesttesttesttesttest"
|
55
59
|
end
|
56
60
|
|
57
61
|
it "returns user name" do
|
58
|
-
base.user_name.
|
62
|
+
expect(base.user_name).to eq "Adam Newman"
|
59
63
|
end
|
60
64
|
|
61
65
|
end
|
@@ -67,18 +71,16 @@ describe PivoFlow::Base do
|
|
67
71
|
'pivo-flow.api-token' => nil,
|
68
72
|
'pivo-flow.project-id' => nil}
|
69
73
|
)
|
70
|
-
PivoFlow::Base.any_instance.stub(:git_config_ok?).and_return(false)
|
71
74
|
|
75
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:git_config_ok?).and_return(false)
|
72
76
|
end
|
73
77
|
|
74
78
|
PivoFlow::Base::KEYS_AND_QUESTIONS.each do |key, value|
|
75
79
|
it "changes #{key} value" do
|
76
|
-
PivoFlow::Base.
|
80
|
+
allow_any_instance_of(PivoFlow::Base).to receive(:ask_question).and_return(key)
|
77
81
|
new_key = key.split(".").last
|
78
|
-
base.options[new_key].
|
82
|
+
expect(base.options[new_key]).to eq key
|
79
83
|
end
|
80
84
|
end
|
81
|
-
|
82
85
|
end
|
83
|
-
|
84
86
|
end
|
data/spec/pivo_flow/cli_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe PivoFlow::Cli do
|
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
# we don't need cli output all over the specs
|
7
|
-
PivoFlow::Cli.
|
7
|
+
allow_any_instance_of(PivoFlow::Cli).to receive(:puts)
|
8
8
|
end
|
9
9
|
|
10
10
|
describe "with no args provided" do
|
@@ -12,7 +12,7 @@ describe PivoFlow::Cli do
|
|
12
12
|
let(:command) { PivoFlow::Cli.new.go! }
|
13
13
|
|
14
14
|
before(:each) do
|
15
|
-
PivoFlow::Cli.
|
15
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:no_method_error).and_return(true)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "calls no_method_error message " do
|
@@ -30,7 +30,7 @@ describe PivoFlow::Cli do
|
|
30
30
|
let(:command) { PivoFlow::Cli.new("invalid_method_name").go! }
|
31
31
|
|
32
32
|
before(:each) do
|
33
|
-
PivoFlow::Cli.
|
33
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:invalid_method_error)
|
34
34
|
end
|
35
35
|
|
36
36
|
it "calls invalid_method_error message" do
|
@@ -44,11 +44,11 @@ describe PivoFlow::Cli do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "with valid command" do
|
47
|
-
cmd
|
47
|
+
let(:cmd) { "stories" }
|
48
48
|
let(:command) { PivoFlow::Cli.new(cmd).go! }
|
49
49
|
|
50
50
|
before do
|
51
|
-
PivoFlow::Cli.
|
51
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(cmd.to_sym)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "runs this command if it is public" do
|
@@ -58,44 +58,27 @@ describe PivoFlow::Cli do
|
|
58
58
|
it "returns 0" do
|
59
59
|
expect(command).to eq 0
|
60
60
|
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "reads story id from file" do
|
65
|
-
|
66
|
-
it "and returns nil if there is no such file" do
|
67
|
-
File.stub(:exists?).and_return(false)
|
68
|
-
PivoFlow::Cli.new.send(:current_story_id).should be_nil
|
69
|
-
end
|
70
|
-
|
71
|
-
it "and returns story id if file exists" do
|
72
|
-
File.stub(:exists?).and_return(true)
|
73
|
-
f = mock('File', :read => "123")
|
74
|
-
File.stub(:open).and_return(f)
|
75
|
-
PivoFlow::Cli.new.send(:current_story_id).should eq "123"
|
76
|
-
end
|
77
61
|
end
|
78
62
|
|
79
63
|
describe "finish method" do
|
80
|
-
|
81
64
|
it "calls finish_story on pivotal object on finish method" do
|
82
|
-
pivo =
|
83
|
-
PivoFlow::Cli.
|
84
|
-
pivo.
|
85
|
-
PivoFlow::Cli.
|
65
|
+
pivo = instance_double("PivoFlow::Pivotal")
|
66
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:pivotal_object).and_return(pivo)
|
67
|
+
expect(pivo).to receive(:finish_story).with("123")
|
68
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:current_story_id).twice.and_return("123")
|
86
69
|
PivoFlow::Cli.new("finish").go!
|
87
70
|
end
|
88
71
|
|
89
72
|
it "returns 1 if there is no current_story_id" do
|
90
|
-
PivoFlow::Cli.
|
91
|
-
PivoFlow::Cli.new.send(:finish).
|
73
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:current_story_id).and_return(nil)
|
74
|
+
expect(PivoFlow::Cli.new.send(:finish)).to eq 1
|
92
75
|
end
|
93
76
|
end
|
94
77
|
|
95
78
|
describe "start method" do
|
96
79
|
|
97
80
|
it "returns 1 if no story given" do
|
98
|
-
PivoFlow::Cli.new.send(:start).
|
81
|
+
expect(PivoFlow::Cli.new.send(:start)).to eq 1
|
99
82
|
end
|
100
83
|
|
101
84
|
end
|
@@ -103,14 +86,14 @@ describe PivoFlow::Cli do
|
|
103
86
|
describe "clear method" do
|
104
87
|
|
105
88
|
it "returns 1 if current story is nil" do
|
106
|
-
PivoFlow::Cli.
|
107
|
-
PivoFlow::Cli.new.send(:clear).
|
89
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:current_story_id).and_return(nil)
|
90
|
+
expect(PivoFlow::Cli.new.send(:clear)).to eq 1
|
108
91
|
end
|
109
92
|
|
110
93
|
|
111
94
|
it "removes file if current story is present" do
|
112
|
-
PivoFlow::Cli.
|
113
|
-
FileUtils.
|
95
|
+
expect_any_instance_of(PivoFlow::Cli).to receive(:current_story_id).and_return(1)
|
96
|
+
expect(FileUtils).to receive(:remove_file).and_return(true)
|
114
97
|
PivoFlow::Cli.new.send(:clear)
|
115
98
|
end
|
116
99
|
|
@@ -121,8 +104,8 @@ describe PivoFlow::Cli do
|
|
121
104
|
methods = [:stories, :start, :info, :finish, :clear, :help, :reconfig, :current, :deliver]
|
122
105
|
methods.each do |method|
|
123
106
|
it "#{method.to_s}" do
|
124
|
-
PivoFlow::Cli.
|
125
|
-
PivoFlow::Cli.new(method.to_s).go
|
107
|
+
allow_any_instance_of(PivoFlow::Cli).to receive(method)
|
108
|
+
expect(PivoFlow::Cli.new(method.to_s).go!).to eq 0
|
126
109
|
end
|
127
110
|
end
|
128
111
|
end
|
@@ -6,66 +6,68 @@ describe PivoFlow::Pivotal do
|
|
6
6
|
|
7
7
|
before do
|
8
8
|
stub_git_config
|
9
|
-
|
9
|
+
|
10
|
+
allow_any_instance_of(PivoFlow::Pivotal).to receive(:puts)
|
11
|
+
|
10
12
|
stub_base_methods(PivoFlow::Pivotal)
|
11
13
|
end
|
12
14
|
|
13
15
|
describe "raises exception" do
|
14
16
|
it "when project id is incorrect" do
|
15
17
|
VCR.use_cassette(:pivotal_fetch_project_not_found) do
|
16
|
-
expect{pivotal.fetch_stories}
|
18
|
+
expect { pivotal.fetch_stories }
|
19
|
+
.to raise_error(PivoFlow::Errors::UnsuccessfulPivotalConnection)
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
20
23
|
it "when api-token is incorrect (unauthorized)" do
|
21
24
|
VCR.use_cassette(:pivotal_fetch_project_unauthorized) do
|
22
|
-
expect{pivotal.fetch_stories}
|
25
|
+
expect { pivotal.fetch_stories }
|
26
|
+
.to raise_error(PivoFlow::Errors::UnsuccessfulPivotalConnection)
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
26
29
|
end
|
27
30
|
|
28
31
|
describe "methods" do
|
29
|
-
|
30
32
|
before(:each) do
|
31
33
|
stub_pivotal_project
|
32
34
|
pivotal.run
|
33
35
|
end
|
34
36
|
|
35
37
|
it "does not call pivotal upon run" do
|
36
|
-
pivotal.options[:project].
|
38
|
+
expect(pivotal.options[:project]).to be_nil
|
37
39
|
end
|
38
40
|
|
39
41
|
it "calls pivotal when necessary" do
|
40
|
-
pivotal.
|
42
|
+
expect(pivotal).to receive(:ensure_project).once
|
41
43
|
pivotal.fetch_stories
|
42
44
|
end
|
43
45
|
|
44
46
|
it "does not call pivotal twice" do
|
45
|
-
PivotalTracker::Project.
|
47
|
+
expect(PivotalTracker::Project).to receive(:find).once
|
46
48
|
2.times { pivotal.fetch_stories }
|
47
49
|
end
|
48
50
|
|
49
51
|
it "user_stories takes only stories owned by current user" do
|
50
|
-
pivotal.user_stories.
|
52
|
+
expect(pivotal.user_stories).to eq [@story_feature]
|
51
53
|
end
|
52
54
|
|
53
55
|
it "unasigned_stories takes only stories with no user" do
|
54
|
-
pivotal.unasigned_stories.
|
56
|
+
expect(pivotal.unasigned_stories).to eq [@story_unassigned]
|
55
57
|
end
|
56
58
|
|
57
59
|
it "show_stories should display stories on output" do
|
58
|
-
pivotal.
|
60
|
+
expect(pivotal).to receive(:list_stories_to_output)
|
59
61
|
pivotal.show_stories
|
60
62
|
end
|
61
63
|
|
62
64
|
describe "story_string" do
|
63
65
|
|
64
66
|
it "includes story id" do
|
65
|
-
pivotal.story_string(@story_feature).
|
67
|
+
expect(pivotal.story_string(@story_feature)).to match(/[##{@story_feature.id}]/) end
|
66
68
|
|
67
69
|
it "includes story name" do
|
68
|
-
pivotal.story_string(@story_feature).
|
70
|
+
expect(pivotal.story_string(@story_feature)).to match(/#{@story_feature.name}/)
|
69
71
|
end
|
70
72
|
|
71
73
|
end
|
@@ -73,9 +75,9 @@ describe PivoFlow::Pivotal do
|
|
73
75
|
describe "deliver" do
|
74
76
|
|
75
77
|
it "list only the stories with 'finished' status" do
|
76
|
-
pivotal.
|
77
|
-
@project.
|
78
|
-
pivotal.
|
78
|
+
expect(pivotal).to receive(:user_name).and_return(@story_finished.owned_by)
|
79
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([@story_finished])
|
80
|
+
expect(pivotal).to receive(:list_stories_to_output).with([@story_finished], "deliver")
|
79
81
|
pivotal.deliver
|
80
82
|
end
|
81
83
|
|
@@ -84,11 +86,11 @@ describe PivoFlow::Pivotal do
|
|
84
86
|
describe "list_stories_to_output" do
|
85
87
|
|
86
88
|
it "returns 1 if stories are nil" do
|
87
|
-
pivotal.list_stories_to_output(nil).
|
89
|
+
expect(pivotal.list_stories_to_output(nil)).to eq 1
|
88
90
|
end
|
89
91
|
|
90
92
|
it "returns 1 if stories are []" do
|
91
|
-
pivotal.list_stories_to_output([]).
|
93
|
+
expect(pivotal.list_stories_to_output([])).to eq 1
|
92
94
|
end
|
93
95
|
|
94
96
|
end
|
@@ -96,9 +98,9 @@ describe PivoFlow::Pivotal do
|
|
96
98
|
describe "show_story" do
|
97
99
|
|
98
100
|
after(:each) do
|
99
|
-
pivotal.
|
101
|
+
allow(pivotal).to receive(:show_stories)
|
100
102
|
# pivotal.stub(:update_story)
|
101
|
-
pivotal.
|
103
|
+
allow(pivotal).to receive(:show_info)
|
102
104
|
|
103
105
|
pivotal.show_story 1
|
104
106
|
end
|
@@ -106,41 +108,41 @@ describe PivoFlow::Pivotal do
|
|
106
108
|
describe "if story's state is 'finished'" do
|
107
109
|
|
108
110
|
before(:each) do
|
109
|
-
@story_feature.
|
110
|
-
pivotal.
|
111
|
+
allow(@story_feature).to receive(:current_state).and_return("finished")
|
112
|
+
allow(pivotal).to receive(:ask_question).and_return("y")
|
111
113
|
end
|
112
114
|
|
113
115
|
it "ask for deliver the story" do
|
114
|
-
pivotal.
|
116
|
+
expect(pivotal).to receive(:ask_question).with(/deliver/)
|
115
117
|
end
|
116
118
|
|
117
119
|
it "updates story on pivotal with 'delivered' status" do
|
118
|
-
@story_feature.
|
120
|
+
expect(@story_feature).to receive(:update).with({ owned_by: @story_feature.owned_by, current_state: :delivered })
|
119
121
|
end
|
120
122
|
|
121
123
|
end
|
122
124
|
|
123
125
|
|
124
126
|
it "shows info about the story" do
|
125
|
-
pivotal.
|
126
|
-
pivotal.
|
127
|
+
allow(pivotal).to receive(:ask_question).and_return("no")
|
128
|
+
expect(pivotal).to receive(:show_info)
|
127
129
|
end
|
128
130
|
|
129
131
|
it "updates the story if user response is 'yes'" do
|
130
|
-
pivotal.
|
131
|
-
pivotal.
|
132
|
+
allow(pivotal).to receive(:ask_question).and_return("yes")
|
133
|
+
expect(pivotal).to receive(:update_story)
|
132
134
|
end
|
133
135
|
|
134
136
|
it "show stories if user response is 'no'" do
|
135
|
-
pivotal.
|
136
|
-
pivotal.
|
137
|
+
allow(pivotal).to receive(:ask_question).and_return("no")
|
138
|
+
expect(pivotal).to receive(:show_stories)
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
142
|
describe "start_story" do
|
141
143
|
|
142
144
|
before(:each) do
|
143
|
-
@story_feature.
|
145
|
+
expect(@story_feature).to receive(:update).with({ current_state: :started, owned_by: pivotal.user_name })
|
144
146
|
end
|
145
147
|
|
146
148
|
it "updates pivotal tracker" do
|
@@ -148,13 +150,12 @@ describe PivoFlow::Pivotal do
|
|
148
150
|
end
|
149
151
|
|
150
152
|
it "returns true on success" do
|
151
|
-
pivotal.start_story(@story_feature.id).
|
153
|
+
expect(pivotal.start_story(@story_feature.id)).to be_truthy
|
152
154
|
end
|
153
|
-
|
154
155
|
end
|
155
156
|
|
156
157
|
it "show_info returns 1 if there is no story" do
|
157
|
-
@project.
|
158
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([])
|
158
159
|
expect(pivotal.show_info).to eq 1
|
159
160
|
end
|
160
161
|
|
@@ -168,47 +169,50 @@ describe PivoFlow::Pivotal do
|
|
168
169
|
|
169
170
|
|
170
171
|
it "is the first of user's started stories" do
|
171
|
-
@project.
|
172
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([@users_story1, @users_story2])
|
172
173
|
|
173
|
-
pivotal.current_story.
|
174
|
+
expect(pivotal.current_story).to eq @users_story1
|
174
175
|
end
|
175
176
|
|
176
177
|
it "is the first of user's stories if he has no started stories" do
|
177
|
-
@project.
|
178
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([@users_story3, @users_story4])
|
178
179
|
|
179
|
-
pivotal.current_story.
|
180
|
+
expect(pivotal.current_story).to eq @users_story3
|
180
181
|
end
|
181
182
|
|
182
183
|
it "is nil if there is no stories assigned to user" do
|
183
|
-
@project.
|
184
|
-
pivotal.current_story.
|
184
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([])
|
185
|
+
expect(pivotal.current_story).to be_nil
|
185
186
|
end
|
186
187
|
|
187
188
|
end
|
188
189
|
|
189
190
|
end
|
190
191
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
192
|
+
def stub_pivotal_project
|
193
|
+
@project = PivotalTracker::Project.new(id: 123456, name: "testproject")
|
194
|
+
|
195
|
+
@story_feature = PivotalTracker::Story.new(
|
196
|
+
id: 1,
|
197
|
+
url: "http://www.pivotaltracker.com/story/show/1",
|
198
|
+
created_at: DateTime.now,
|
199
|
+
project_id: 123456,
|
200
|
+
name: "story no 1",
|
201
|
+
description: "story description",
|
202
|
+
story_type: "feature",
|
203
|
+
estimate: 3,
|
204
|
+
current_state: "started",
|
205
|
+
requested_by: "Paul Newman",
|
206
|
+
owned_by: "Adam Newman",
|
207
|
+
labels: "first,second"
|
208
|
+
)
|
209
|
+
|
210
|
+
allow(@story_feature).to receive_message_chain(:update).and_return(double(errors: []))
|
211
|
+
@story_unassigned = PivotalTracker::Story.new(owned_by: nil, name: "test", current_state: "started")
|
212
|
+
@story_rejected = PivotalTracker::Story.new(current_state: "rejected", owned_by: "Mark Marco", name: "test_rejected")
|
213
|
+
@story_finished = PivotalTracker::Story.new(current_state: "finished", owned_by: "Mark Marco", name: "finished")
|
214
|
+
|
215
|
+
allow(@project).to receive_message_chain(:stories, :all).and_return([@story_feature, @story_unassigned, @story_rejected, @story_finished])
|
216
|
+
allow(PivotalTracker::Project).to receive(:find).and_return(@project)
|
217
|
+
end
|
214
218
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivoFlow::State do
|
4
|
+
describe "#current_story_id_file_path" do
|
5
|
+
before do
|
6
|
+
allow(PivoFlow::State).to receive(:current_branch_name) { "cool-branch" }
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a path to a branch-based file name" do
|
10
|
+
expect(PivoFlow::State.current_story_id_file_path).to eq(
|
11
|
+
"#{Dir.pwd}/tmp/.pivo_flow/stories/cool-branch"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#current_story_id" do
|
17
|
+
let(:tmp_file) { "#{Dir.pwd}/tmp/.pivo_flow/stories/cool-branch" }
|
18
|
+
|
19
|
+
before do
|
20
|
+
allow(PivoFlow::State).to receive(:current_branch_name) { "cool-branch" }
|
21
|
+
|
22
|
+
FileUtils.mkdir_p(PivoFlow::State.story_id_tmp_path)
|
23
|
+
File.write(tmp_file, "123456")
|
24
|
+
end
|
25
|
+
|
26
|
+
after { FileUtils.remove_file(tmp_file) }
|
27
|
+
|
28
|
+
it "should read it from the tmp file" do
|
29
|
+
expect(PivoFlow::State.current_story_id).to eq("123456")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return nil if there's no file for it yet" do
|
33
|
+
allow(PivoFlow::State).to receive(:current_branch_name) { "different" }
|
34
|
+
|
35
|
+
expect(PivoFlow::State.current_story_id).to be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,18 +12,26 @@ VCR.configure do |c|
|
|
12
12
|
c.cassette_library_dir = 'spec/pivo_flow/vcr_cassettes'
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
module StubHelpers
|
16
|
+
def stub_git_config(options = {})
|
17
|
+
git_options = {
|
18
|
+
"pivo-flow.api-token" => "testtesttesttesttesttesttesttest",
|
19
|
+
"pivo-flow.project-id" => "123456",
|
20
|
+
"user.name" => "Adam Newman"
|
21
|
+
}.merge(options)
|
22
22
|
|
23
|
+
allow(Grit::Repo).to receive(:new) do
|
24
|
+
instance_double('Grit::Repo', config: git_options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def stub_base_methods(klass)
|
29
|
+
allow_any_instance_of(klass).to receive(:git_hook_needed?) { false }
|
30
|
+
allow_any_instance_of(klass).to receive(:git_directory_present?) { true }
|
31
|
+
allow_any_instance_of(klass).to receive(:git_config_ok?) { true }
|
32
|
+
end
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
klass.any_instance.stub(:git_directory_present?).and_return(true)
|
28
|
-
klass.any_instance.stub(:git_config_ok?).and_return(true)
|
35
|
+
RSpec.configure do |config|
|
36
|
+
config.include StubHelpers
|
29
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pivo_flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.7'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Nowak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pivotal-tracker
|
@@ -148,7 +148,7 @@ extra_rdoc_files: []
|
|
148
148
|
files:
|
149
149
|
- ".gitignore"
|
150
150
|
- ".rspec"
|
151
|
-
-
|
151
|
+
- CHANGELOG.md
|
152
152
|
- Gemfile
|
153
153
|
- LICENSE
|
154
154
|
- README.md
|
@@ -161,11 +161,13 @@ files:
|
|
161
161
|
- lib/pivo_flow/core_extensions.rb
|
162
162
|
- lib/pivo_flow/errors.rb
|
163
163
|
- lib/pivo_flow/pivotal.rb
|
164
|
+
- lib/pivo_flow/state.rb
|
164
165
|
- lib/pivo_flow/version.rb
|
165
166
|
- pivo_flow.gemspec
|
166
167
|
- spec/pivo_flow/base_spec.rb
|
167
168
|
- spec/pivo_flow/cli_spec.rb
|
168
169
|
- spec/pivo_flow/pivotal_spec.rb
|
170
|
+
- spec/pivo_flow/state_spec.rb
|
169
171
|
- spec/pivo_flow/vcr_cassettes/pivotal_fetch_project_not_found.yml
|
170
172
|
- spec/pivo_flow/vcr_cassettes/pivotal_fetch_project_unauthorized.yml
|
171
173
|
- spec/spec_helper.rb
|
@@ -188,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
190
|
version: '0'
|
189
191
|
requirements: []
|
190
192
|
rubyforge_project:
|
191
|
-
rubygems_version: 2.
|
193
|
+
rubygems_version: 2.6.11
|
192
194
|
signing_key:
|
193
195
|
specification_version: 4
|
194
196
|
summary: Simple pivotal tracker integration for day to day work with git
|
@@ -196,7 +198,7 @@ test_files:
|
|
196
198
|
- spec/pivo_flow/base_spec.rb
|
197
199
|
- spec/pivo_flow/cli_spec.rb
|
198
200
|
- spec/pivo_flow/pivotal_spec.rb
|
201
|
+
- spec/pivo_flow/state_spec.rb
|
199
202
|
- spec/pivo_flow/vcr_cassettes/pivotal_fetch_project_not_found.yml
|
200
203
|
- spec/pivo_flow/vcr_cassettes/pivotal_fetch_project_unauthorized.yml
|
201
204
|
- spec/spec_helper.rb
|
202
|
-
has_rdoc:
|