crab 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -124,7 +124,6 @@ To do
124
124
  -----
125
125
 
126
126
  - Add a config command + .crab/config file to hold settings like project, etc
127
- - Ability to create and delete stories with all mandatory fields from the command line
128
127
  - Add a `push` subcommand which parses a Cucumber feature and adds or updates it in Rally
129
128
  - Add a way to create, edit and delete test cases / scenarios from the command line
130
129
  - `pull` is not very smart and could detect feature files being moved from one dir to another
@@ -1,10 +1,10 @@
1
1
  Feature: Find Text in Stories
2
-
2
+
3
3
  In order to find the story ID
4
4
  A lazy developer
5
5
  Wants to search for arbitrary bits of text
6
6
 
7
- Background:
7
+ Background:
8
8
  Given I am logged in
9
9
  And I have selected my test project
10
10
 
@@ -13,7 +13,6 @@ Feature: Find Text in Stories
13
13
  Then the output should contain:
14
14
  """
15
15
  US4988: Sample Crab Story (grooming)
16
- US4999: Sample Crab Parent Story (grooming)
17
16
  US5000: Sample Crab Parent Story (grooming)
18
17
  """
19
18
 
@@ -1,6 +1,6 @@
1
1
  @quick
2
2
  Feature: Subcommand Help
3
-
3
+
4
4
  In order to learn how to use crab
5
5
  A newbie developer
6
6
  Wants to see a useful help message when she runs crab with the wrong arguments
@@ -11,14 +11,15 @@ Feature: Subcommand Help
11
11
 
12
12
  Scenario: Help
13
13
  When I run `crab -h`
14
- Then the output should contain " create Create a new story in Rally"
15
- Then the output should contain " delete Delete an existing story in Rally"
16
- And the output should contain " find Find stories by text in name, description or notes"
17
- And the output should contain " login Persistently authenticate user with Rally"
18
- And the output should contain " project Persistently select project to work with in Rally"
19
- And the output should contain " pull Downloads stories (and its test cases) as Cucumber feature files"
20
- And the output should contain " show Show a story (and its test cases) as a Cucumber feature"
21
- And the output should contain " update Update a story (name, estimate, etc)"
14
+ Then the output should contain " create Create a new story in Rally"
15
+ Then the output should contain " delete Delete an existing story in Rally"
16
+ And the output should contain " find Find stories by text in name, description or notes"
17
+ And the output should contain " login Persistently authenticate user with Rally"
18
+ And the output should contain " project Persistently select project to work with in Rally"
19
+ And the output should contain " pull Downloads stories (and its test cases) as Cucumber feature files"
20
+ And the output should contain " show Show a story (and its test cases) as a Cucumber feature"
21
+ And the output should contain " testcase Manage test cases in a story (add, update, delete)"
22
+ And the output should contain " update Update a story (name, estimate, etc)"
22
23
 
23
24
  Scenario: Bogus Subcommand
24
25
  When I run `crab bogus`
@@ -63,6 +64,13 @@ Feature: Subcommand Help
63
64
  Usage: crab [options] delete story [options]
64
65
  """
65
66
 
67
+ Scenario: Testcase Subcommand
68
+ When I run `crab testcase --help`
69
+ Then the output should contain "crab testcase: manage test cases in a story (add, update, delete)"
70
+ And the output should contain "Usage: crab [options] testcase add story name [options]"
71
+ And the output should contain "crab [options] testcase update testcase [options]"
72
+ And the output should contain "crab [options] testcase delete testcase [options]"
73
+
66
74
  Scenario: Update Subcommand
67
75
  When I run `crab update --help`
68
76
  Then the output should contain:
data/lib/crab.rb CHANGED
@@ -1,18 +1,33 @@
1
1
  require "crab/version"
2
2
 
3
+ # common dependencies
4
+ require 'trollop'
5
+ require 'fileutils'
6
+ require 'gherkin/i18n'
7
+ require 'highline/import'
8
+ require 'active_support/all'
9
+ require 'rally_rest_api'
10
+ require 'sanitize'
11
+
12
+ # internals
3
13
  require "crab/utilities"
4
14
  require "crab/rally"
5
15
  require "crab/story"
6
16
  require "crab/cli"
7
- require "crab/pull"
8
- require "crab/login"
9
- require "crab/find"
10
- require "crab/update"
11
- require "crab/show"
12
17
  require "crab/scenario"
13
- require "crab/project"
14
- require "crab/create"
15
- require "crab/delete"
18
+
19
+ # supported commands
20
+ require "crab/commands/update"
21
+ require "crab/commands/pull"
22
+ require "crab/commands/find"
23
+ require "crab/commands/login"
24
+ require "crab/commands/show"
25
+ require "crab/commands/project"
26
+ require "crab/commands/create"
27
+ require "crab/commands/delete"
28
+ require "crab/commands/testcase"
29
+
30
+ # cucumber support
16
31
  require "crab/cucumber_feature"
17
32
  require "crab/cucumber_scenario"
18
33
 
data/lib/crab/cli.rb CHANGED
@@ -1,8 +1,6 @@
1
- require 'trollop'
2
-
3
1
  module Crab
4
2
 
5
- SUB_COMMANDS = %w(pull login list update show find project create delete)
3
+ SUB_COMMANDS = %w(pull login list update show find project create delete testcase)
6
4
 
7
5
  class CLI
8
6
  def self.start
@@ -11,112 +9,24 @@ module Crab
11
9
  banner """
12
10
  crab version #{Crab::VERSION}: A Cucumber-Rally bridge
13
11
 
14
- create Create a new story in Rally
15
- delete Delete an existing story in Rally
16
- find Find stories by text in name, description or notes
17
- login Persistently authenticate user with Rally
18
- project Persistently select project to work with in Rally
19
- pull Downloads stories (and its test cases) as Cucumber feature files
20
- show Show a story (and its test cases) as a Cucumber feature
21
- update Update a story (name, estimate, etc)
12
+ create Create a new story in Rally
13
+ delete Delete an existing story in Rally
14
+ find Find stories by text in name, description or notes
15
+ login Persistently authenticate user with Rally
16
+ project Persistently select project to work with in Rally
17
+ pull Downloads stories (and its test cases) as Cucumber feature files
18
+ show Show a story (and its test cases) as a Cucumber feature
19
+ testcase Manage test cases in a story (add, update, delete)
20
+ update Update a story (name, estimate, etc)
22
21
  """
23
22
  stop_on SUB_COMMANDS
24
23
  end
25
24
 
26
25
  cmd = ARGV.shift # get the subcommand
27
- case cmd
28
- when "pull" # parse delete options
29
- cmd_opts = Trollop::options do
30
- banner "crab pull: pulls stories from Rally and writes them out as Cucumber features
31
-
32
- Usage: crab [options] pull story1 [story2 ...]"
33
- opt :language, "Language to generate Cucumber features in (ISO code)", :default => "en", :short => "-l"
34
- end
35
-
36
- Crab::Pull.new(global_opts, cmd_opts, ARGV).run
37
-
38
- when "show"
39
- cmd_opts = Trollop::options do
40
- banner "crab show: displays a story in Rally as a Cucumber feature
41
-
42
- Usage: crab [options] show story"
43
- opt :language, "Language to display Cucumber features in (ISO code)", :default => "en", :short => "-l"
44
- end
45
-
46
- Crab::Show.new(global_opts, cmd_opts, ARGV).run
47
-
48
- when "login"
49
- cmd_opts = Trollop::options do
50
- banner "crab login: logs into Rally
51
-
52
- Usage: crab [options] login"
53
- opt :username, "Username", :type => String, :short => "-u"
54
- opt :password, "Password", :type => String, :short => "-p"
55
- end
56
-
57
- Crab::Login.new(global_opts, cmd_opts).run
58
-
59
- when "update"
60
- cmd_opts = Trollop::options do
61
- banner "crab update: update a story in Rally
62
-
63
- Usage: crab [options] update story [options]"
64
- opt :name, "Name (title)", :type => String, :short => "-n"
65
- opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
66
- opt :estimate, "Estimate", :type => :int, :short => "-e"
67
- opt :iteration, "Iteration", :type => String, :short => "-i"
68
- opt :release, "Release", :type => String, :short => "-r"
69
- opt :blocked, "Blocked", :short => "-b"
70
- opt :unblocked, "Unblocked", :short => "-u"
71
- opt :parent, "Parent", :type => String, :short => "-p"
72
- end
73
-
74
- Crab::Update.new(global_opts, cmd_opts, ARGV).run
75
-
76
- when "find"
77
- cmd_opts = Trollop::options do
78
- banner "crab find: find a story in Rally
26
+ Trollop::die "Unknown subcommand" unless cmd
27
+ Trollop::die "Unknown subcommand #{cmd.inspect}" unless Crab::Commands.const_defined? cmd.capitalize
79
28
 
80
- Usage: crab [options] find [options] [text]"
81
- opt :project, "Project to use (required unless set by 'crab project')", :short => "-p", :type => String
82
- end
83
-
84
- Crab::Find.new(global_opts, cmd_opts, ARGV).run
85
-
86
- when "project"
87
- cmd_opts = Trollop::options do
88
- banner "crab project: persistently select project to work with in Rally
89
-
90
- Usage: crab [options] project name"
91
- end
92
-
93
- Crab::Project.new(global_opts, cmd_opts, ARGV).run
94
-
95
- when "create"
96
- cmd_opts = Trollop::options do
97
- banner "crab create: create a new story in Rally
98
-
99
- Usage: crab [options] create name [options]"
100
- end
101
-
102
- Crab::Create.new(global_opts, cmd_opts, ARGV).run
103
-
104
- when "delete"
105
- cmd_opts = Trollop::options do
106
- banner "crab delete: delete an existing story in Rally
107
-
108
- Usage: crab [options] delete story [options]"
109
- end
110
-
111
- Crab::Delete.new(global_opts, cmd_opts, ARGV).run
112
-
113
- else
114
- if cmd
115
- Trollop::die "Unknown subcommand #{cmd.inspect}"
116
- else
117
- Trollop::die "Unknown subcommand"
118
- end
119
- end
29
+ Crab::Commands.const_get(cmd.capitalize).new(global_opts, ARGV).run
120
30
  end
121
31
  end
122
32
  end
@@ -1,12 +1,16 @@
1
- module Crab
1
+ module Crab::Commands
2
2
 
3
3
  class Create
4
4
 
5
- def initialize(global_opts, cmd_opts, args)
5
+ def initialize(global_opts, args)
6
6
  @global_opts = global_opts
7
- @cmd_opts = cmd_opts
8
7
  @args = args
9
- @rally = Rally.new
8
+ @cmd_opts = Trollop::options do
9
+ banner "crab create: create a new story in Rally
10
+
11
+ Usage: crab [options] create name [options]"
12
+ end
13
+ @rally = Crab::Rally.new
10
14
  end
11
15
 
12
16
  def run
@@ -1,12 +1,18 @@
1
- module Crab
1
+ module Crab::Commands
2
2
 
3
3
  class Delete
4
4
 
5
- def initialize(global_opts, cmd_opts, args)
5
+ def initialize(global_opts, args)
6
6
  @global_opts = global_opts
7
- @cmd_opts = cmd_opts
8
7
  @args = args
9
- @rally = Rally.new
8
+
9
+ @cmd_opts = Trollop::options do
10
+ banner "crab delete: delete an existing story in Rally
11
+
12
+ Usage: crab [options] delete story [options]"
13
+ end
14
+
15
+ @rally = Crab::Rally.new
10
16
  end
11
17
 
12
18
  def run
@@ -1,13 +1,21 @@
1
- module Crab
1
+ module Crab::Commands
2
+
2
3
  class Find
3
4
 
4
- include Utilities
5
+ include Crab::Utilities
5
6
 
6
- def initialize(global_opts, cmd_opts, args)
7
+ def initialize(global_opts, args)
7
8
  @global_opts = global_opts
8
- @cmd_opts = cmd_opts
9
9
  @args = args
10
- @rally = Rally.new
10
+
11
+ @cmd_opts = Trollop::options do
12
+ banner "crab find: find a story in Rally
13
+
14
+ Usage: crab [options] find [options] [text]"
15
+ opt :project, "Project to use (required unless set by 'crab project')", :short => "-p", :type => String
16
+ end
17
+
18
+ @rally = Crab::Rally.new
11
19
  end
12
20
 
13
21
  def run
@@ -1,13 +1,18 @@
1
- require 'highline/import'
1
+ module Crab::Commands
2
2
 
3
- module Crab
4
3
  class Login
5
4
 
6
- include Utilities
5
+ include Crab::Utilities
7
6
 
8
- def initialize(global_opts, cmd_opts)
7
+ def initialize(global_opts, args)
9
8
  @global_opts = global_opts
10
- @cmd_opts = cmd_opts
9
+ @cmd_opts = Trollop::options do
10
+ banner "crab login: logs into Rally
11
+
12
+ Usage: crab [options] login"
13
+ opt :username, "Username", :type => String, :short => "-u"
14
+ opt :password, "Password", :type => String, :short => "-p"
15
+ end
11
16
  end
12
17
 
13
18
  def run
@@ -1,4 +1,4 @@
1
- module Crab
1
+ module Crab::Commands
2
2
  class Project
3
3
 
4
4
  def self.current_project_name
@@ -7,11 +7,17 @@ module Crab
7
7
  end
8
8
  end
9
9
 
10
- def initialize(global_opts, cmd_opts, args)
10
+ def initialize(global_opts, args)
11
11
  @global_opts = global_opts
12
- @cmd_opts = cmd_opts
13
12
  @args = args
14
- @rally = Rally.new
13
+
14
+ @cmd_opts = Trollop::options do
15
+ banner "crab project: persistently select project to work with in Rally
16
+
17
+ Usage: crab [options] project name"
18
+ end
19
+
20
+ @rally = Crab::Rally.new
15
21
  end
16
22
 
17
23
  def run
@@ -0,0 +1,37 @@
1
+ module Crab::Commands
2
+
3
+ class Pull
4
+
5
+ def initialize(global_opts, args)
6
+ @global_opts = global_opts
7
+ @story_numbers = args
8
+
9
+ @cmd_opts = Trollop::options do
10
+ banner "crab pull: pulls stories from Rally and writes them out as Cucumber features
11
+
12
+ Usage: crab [options] pull story1 [story2 ...]"
13
+ opt :language, "Language to generate Cucumber features in (ISO code)", :default => "en", :short => "-l"
14
+ end
15
+
16
+ @rally = Crab::Rally.new
17
+ end
18
+
19
+ def run
20
+ @rally.connect
21
+
22
+ @story_numbers.each do |story_number|
23
+ story = @rally.find_story_with_id story_number
24
+ Trollop::die "Could not find story with ID #{story_number}" if story.nil?
25
+
26
+ puts "#{story.formatted_id}: #{story.full_file_name}"
27
+
28
+ FileUtils.mkdir_p File.dirname(story.full_file_name)
29
+ FileUtils.touch story.full_file_name
30
+
31
+ File.open(story.full_file_name, "w") do |file|
32
+ file.write Crab::CucumberFeature.new(@cmd_opts[:language]).generate_from story
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module Crab::Commands
2
+
3
+ class Show
4
+ def initialize(global_opts, args)
5
+ @global_opts = global_opts
6
+ @cmd_opts = Trollop::options do
7
+ banner "crab show: displays a story in Rally as a Cucumber feature
8
+
9
+ Usage: crab [options] show story"
10
+ opt :language, "Language to display Cucumber features in (ISO code)", :default => "en", :short => "-l"
11
+ end
12
+
13
+ @story_id = args.first
14
+ @rally = Crab::Rally.new
15
+ end
16
+
17
+ def run
18
+ @rally.connect
19
+
20
+ story = @rally.find_story_with_id @story_id
21
+
22
+ puts Crab::CucumberFeature.new(@cmd_opts[:language]).generate_from story
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Crab::Commands
2
+
3
+ class Testcase
4
+
5
+ def initialize(global_opts, args)
6
+ @global_opts = global_opts
7
+ @args = args
8
+ @cmd_opts = Trollop::options do
9
+ banner "crab testcase: manage test cases in a story (add, update, delete)
10
+
11
+ Usage: crab [options] testcase add story name [options]
12
+ crab [options] testcase update testcase [options]
13
+ crab [options] testcase delete testcase [options]"
14
+ end
15
+ end
16
+
17
+ def run
18
+ end
19
+ end
20
+ end
@@ -1,11 +1,26 @@
1
- module Crab
1
+ module Crab::Commands
2
+
2
3
  class Update
3
- def initialize(global_opts, cmd_opts, args)
4
+
5
+ def initialize(global_opts, args)
4
6
  @global_opts = global_opts
5
- @cmd_opts = cmd_opts
6
7
  @args = args
7
8
 
8
- @rally = Rally.new
9
+ @cmd_opts = Trollop::options do
10
+ banner "crab update: update a story in Rally
11
+
12
+ Usage: crab [options] update story [options]"
13
+ opt :name, "Name (title)", :type => String, :short => "-n"
14
+ opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
15
+ opt :estimate, "Estimate", :type => :int, :short => "-e"
16
+ opt :iteration, "Iteration", :type => String, :short => "-i"
17
+ opt :release, "Release", :type => String, :short => "-r"
18
+ opt :blocked, "Blocked", :short => "-b"
19
+ opt :unblocked, "Unblocked", :short => "-u"
20
+ opt :parent, "Parent", :type => String, :short => "-p"
21
+ end
22
+
23
+ @rally = Crab::Rally.new
9
24
  end
10
25
 
11
26
  def run
@@ -1,6 +1,3 @@
1
- require 'fileutils'
2
- require 'gherkin/i18n'
3
-
4
1
  module Crab
5
2
 
6
3
  class CucumberFeature
data/lib/crab/rally.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'rally_rest_api'
2
-
3
1
  module Crab
4
2
  class Rally
5
3
 
data/lib/crab/story.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'sanitize'
2
-
3
1
  module Crab
4
2
 
5
3
  class Story
@@ -11,7 +11,7 @@ module Crab
11
11
  end
12
12
 
13
13
  def valid_project_name(cmd_opts)
14
- project_name = cmd_opts[:project_given] ? cmd_opts[:project] : Crab::Project.current_project_name
14
+ project_name = cmd_opts[:project_given] ? cmd_opts[:project] : Crab::Commands::Project.current_project_name
15
15
  Trollop::die :project, "must be specified" if project_name.blank?
16
16
  project_name
17
17
  end
data/lib/crab/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Crab
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crab
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 4
10
- version: 0.1.4
9
+ - 5
10
+ version: 0.1.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Carlos Villela
@@ -173,19 +173,20 @@ files:
173
173
  - features/update-story-in-rally.feature
174
174
  - lib/crab.rb
175
175
  - lib/crab/cli.rb
176
- - lib/crab/create.rb
176
+ - lib/crab/commands/create.rb
177
+ - lib/crab/commands/delete.rb
178
+ - lib/crab/commands/find.rb
179
+ - lib/crab/commands/login.rb
180
+ - lib/crab/commands/project.rb
181
+ - lib/crab/commands/pull.rb
182
+ - lib/crab/commands/show.rb
183
+ - lib/crab/commands/testcase.rb
184
+ - lib/crab/commands/update.rb
177
185
  - lib/crab/cucumber_feature.rb
178
186
  - lib/crab/cucumber_scenario.rb
179
- - lib/crab/delete.rb
180
- - lib/crab/find.rb
181
- - lib/crab/login.rb
182
- - lib/crab/project.rb
183
- - lib/crab/pull.rb
184
187
  - lib/crab/rally.rb
185
188
  - lib/crab/scenario.rb
186
- - lib/crab/show.rb
187
189
  - lib/crab/story.rb
188
- - lib/crab/update.rb
189
190
  - lib/crab/utilities.rb
190
191
  - lib/crab/version.rb
191
192
  has_rdoc: true
data/lib/crab/pull.rb DELETED
@@ -1,32 +0,0 @@
1
- require 'active_support/all'
2
-
3
- module Crab
4
-
5
- class Pull
6
-
7
- def initialize(global_opts, cmd_opts, story_numbers)
8
- @global_opts = global_opts
9
- @cmd_opts = cmd_opts
10
- @story_numbers = story_numbers
11
- @rally = Crab::Rally.new
12
- end
13
-
14
- def run
15
- @rally.connect
16
-
17
- @story_numbers.each do |story_number|
18
- story = @rally.find_story_with_id story_number
19
- Trollop::die "Could not find story with ID #{story_number}" if story.nil?
20
-
21
- puts "#{story.formatted_id}: #{story.full_file_name}"
22
-
23
- ::FileUtils.mkdir_p File.dirname(story.full_file_name)
24
- ::FileUtils.touch story.full_file_name
25
-
26
- File.open(story.full_file_name, "w") do |file|
27
- file.write CucumberFeature.new(@cmd_opts[:language]).generate_from story
28
- end
29
- end
30
- end
31
- end
32
- end
data/lib/crab/show.rb DELETED
@@ -1,17 +0,0 @@
1
- module Crab
2
- class Show
3
- def initialize(global_opts, cmd_opts, args)
4
- @global_opts = global_opts
5
- @cmd_opts = cmd_opts
6
- @story_id = args.first
7
- @rally = Rally.new
8
- end
9
-
10
- def run
11
- @rally.connect
12
-
13
- story = @rally.find_story_with_id @story_id
14
- puts CucumberFeature.new(@cmd_opts[:language]).generate_from story
15
- end
16
- end
17
- end