crab 0.1.4 → 0.1.5

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.
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