cuki 0.0.6 → 0.0.7

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/Gemfile CHANGED
@@ -2,6 +2,7 @@ source "http://rubygems.org"
2
2
 
3
3
  gem 'httpclient'
4
4
  gem 'nokogiri'
5
+ gem "parallel"
5
6
 
6
7
  group :development do
7
8
  gem "shoulda", ">= 0"
data/Gemfile.lock CHANGED
@@ -32,6 +32,7 @@ GEM
32
32
  rake
33
33
  json (1.6.1)
34
34
  nokogiri (1.5.0)
35
+ parallel (0.5.9)
35
36
  rack (1.3.4)
36
37
  rake (0.9.2)
37
38
  rcov (0.9.11)
@@ -60,6 +61,7 @@ DEPENDENCIES
60
61
  httpclient
61
62
  jeweler (~> 1.6.4)
62
63
  nokogiri
64
+ parallel
63
65
  rcov
64
66
  rspec
65
67
  shoulda
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
data/cucumber.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ default: '--require features/'
data/cuki.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cuki"
8
- s.version = "0.0.6"
8
+ s.version = "0.0.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andy Waite"]
12
- s.date = "2011-10-16"
12
+ s.date = "2011-10-17"
13
13
  s.description = ""
14
14
  s.email = "andy@andywaite.com"
15
15
  s.executables = ["cuki"]
@@ -28,10 +28,12 @@ Gem::Specification.new do |s|
28
28
  "Rakefile",
29
29
  "VERSION",
30
30
  "bin/cuki",
31
+ "cucumber.yml",
31
32
  "cuki.gemspec",
32
33
  "cuki.yaml.sample",
33
34
  "features/pull/pull.feature",
34
35
  "features/pull/pull_single.feature",
36
+ "features/pull/splitting.feature",
35
37
  "features/pull/tables.feature",
36
38
  "features/pull/tags.feature",
37
39
  "features/pull/textile.feature",
@@ -43,6 +45,7 @@ Gem::Specification.new do |s|
43
45
  "features/support/env.rb",
44
46
  "lib/cuki.rb",
45
47
  "lib/pusher.rb",
48
+ "lib/string_utils.rb",
46
49
  "spec/cuki_spec.rb",
47
50
  "spec/spec_helper.rb"
48
51
  ]
@@ -58,6 +61,7 @@ Gem::Specification.new do |s|
58
61
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
59
62
  s.add_runtime_dependency(%q<httpclient>, [">= 0"])
60
63
  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
64
+ s.add_runtime_dependency(%q<parallel>, [">= 0"])
61
65
  s.add_development_dependency(%q<shoulda>, [">= 0"])
62
66
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
63
67
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -66,6 +70,7 @@ Gem::Specification.new do |s|
66
70
  else
67
71
  s.add_dependency(%q<httpclient>, [">= 0"])
68
72
  s.add_dependency(%q<nokogiri>, [">= 0"])
73
+ s.add_dependency(%q<parallel>, [">= 0"])
69
74
  s.add_dependency(%q<shoulda>, [">= 0"])
70
75
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
71
76
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -75,6 +80,7 @@ Gem::Specification.new do |s|
75
80
  else
76
81
  s.add_dependency(%q<httpclient>, [">= 0"])
77
82
  s.add_dependency(%q<nokogiri>, [">= 0"])
83
+ s.add_dependency(%q<parallel>, [">= 0"])
78
84
  s.add_dependency(%q<shoulda>, [">= 0"])
79
85
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
80
86
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -38,12 +38,12 @@ Feature: Pull
38
38
  This feature describes removing a product
39
39
  </div>
40
40
  """
41
- When I run `cuki pull`
41
+ When I run `cuki pull --skip-autoformat --skip-header`
42
42
  Then the file "features/products/add_product.feature" should contain exactly:
43
43
  """
44
44
  Feature: Add Product
45
45
 
46
- http://example.com/pages/editpage.action?pageId=123
46
+ http://example.com/pages/viewpage.action?pageId=123
47
47
 
48
48
 
49
49
  This feature describes adding a product
@@ -53,7 +53,7 @@ Feature: Pull
53
53
  """
54
54
  Feature: Remove Product
55
55
 
56
- http://example.com/pages/editpage.action?pageId=456
56
+ http://example.com/pages/viewpage.action?pageId=456
57
57
 
58
58
 
59
59
  This feature describes removing a product
@@ -23,7 +23,7 @@ Feature: Pull single
23
23
  This feature describes removing a product
24
24
  </div>
25
25
  """
26
- When I run `cuki pull features/products/add_product.feature`
26
+ When I run `cuki pull features/products/add_product.feature --skip-autoformat --skip-header`
27
27
  Then a file named "features/products/add_product.feature" should exist
28
28
  But the file "features/products/remove_product.feature" should not exist
29
29
 
@@ -0,0 +1,67 @@
1
+ Feature: Splitting
2
+
3
+ Instead of association one wiki page per feature file, you can split a wiki file across multiple feature files.
4
+
5
+ @announce
6
+ Scenario: Pull all features
7
+ Given a file named "config/cuki.yaml" with:
8
+ """
9
+ ---
10
+ host: http://example.com
11
+ container: !ruby/regexp '/h1\. Acceptance Criteria(.*)h1\./m'
12
+ mappings:
13
+ 123: features/products
14
+ """
15
+ And a Confluence page on "example.com" with id 123:
16
+ """
17
+ <input id="content-title" value="Product Management">
18
+ <div id="markupTextarea">
19
+ h1. Acceptance Criteria
20
+
21
+ Something
22
+
23
+ h2. Add Product
24
+
25
+ This feature describes adding a product
26
+
27
+ h6. Scenario: Scenario A
28
+
29
+ h2. Remove Product
30
+
31
+ This feature describes removing a product
32
+
33
+ h6. Scenario Outline: Scenario B
34
+
35
+ h1. Next Section
36
+ </div>
37
+ """
38
+ When I run `cuki pull --skip-autoformat --skip-header`
39
+ Then the file "features/products/add_product.feature" should contain exactly:
40
+ """
41
+ Feature: Add Product
42
+
43
+
44
+
45
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
46
+
47
+ This feature describes adding a product
48
+
49
+ Scenario: Scenario A
50
+
51
+
52
+ """
53
+ And the file "features/products/remove_product.feature" should contain exactly:
54
+ """
55
+ Feature: Remove Product
56
+
57
+
58
+
59
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-RemoveProduct
60
+
61
+ This feature describes removing a product
62
+
63
+ Scenario Outline: Scenario B
64
+
65
+
66
+ """
67
+
@@ -21,12 +21,12 @@ Feature: Tables
21
21
  | b | 2 |
22
22
  </div>
23
23
  """
24
- When I run `cuki pull`
24
+ When I run `cuki pull --skip-autoformat --skip-header`
25
25
  Then the file "features/products/add_product.feature" should contain exactly:
26
26
  """
27
27
  Feature: Add Product
28
28
 
29
- http://example.com/pages/editpage.action?pageId=123
29
+ http://example.com/pages/viewpage.action?pageId=123
30
30
 
31
31
 
32
32
  Scenario: Foo
@@ -18,13 +18,13 @@ Feature: Tags
18
18
  h5. Scenario: Foo
19
19
  </div>
20
20
  """
21
- When I run `cuki pull`
21
+ When I run `cuki pull --skip-autoformat --skip-header`
22
22
  Then the file "features/products/add_product.feature" should contain exactly:
23
23
  """
24
24
  @draft
25
25
  Feature: Add Product
26
26
 
27
- http://example.com/pages/editpage.action?pageId=123
27
+ http://example.com/pages/viewpage.action?pageId=123
28
28
 
29
29
 
30
30
  Scenario: Foo
@@ -17,12 +17,12 @@ Feature: Textile
17
17
  h6. Scenario Outline: Bar
18
18
  </div>
19
19
  """
20
- When I run `cuki pull`
20
+ When I run `cuki pull --skip-autoformat --skip-header`
21
21
  Then the file "features/products/add_product.feature" should contain exactly:
22
22
  """
23
23
  Feature: Add Product
24
24
 
25
- http://example.com/pages/editpage.action?pageId=123
25
+ http://example.com/pages/viewpage.action?pageId=123
26
26
 
27
27
 
28
28
  Scenario: Foo
@@ -19,7 +19,7 @@ Feature: Push
19
19
  """
20
20
  This is my feature
21
21
  """
22
- When I run `cuki push features/products/add_product.feature`
22
+ When I run `cuki push features/products/add_product.feature --skip-autoformat
23
23
  Then the push should be successful
24
24
 
25
25
  @pending
@@ -4,7 +4,7 @@ Given /^a Confluence page on "([^"]*)" with id (\d+):$/ do |host, id, content|
4
4
  # the URLs to be stubbed
5
5
 
6
6
  @stubs ||= {}
7
- @stubs["http://#{host}/pages/editpage.action?pageId=#{id}"] = content
7
+ @stubs["http://#{host}/pages/viewpage.action?pageId=#{id}"] = content
8
8
 
9
9
  File.open('stubs.json', 'w') do |f|
10
10
  f.write @stubs.to_json
data/lib/cuki.rb CHANGED
@@ -4,6 +4,8 @@ require 'nokogiri'
4
4
  require 'yaml'
5
5
  require 'CGI'
6
6
  require 'json'
7
+ require 'parallel'
8
+ require File.dirname(__FILE__) + '/string_utils.rb'
7
9
 
8
10
  # terrible hack
9
11
  if File.exist?('stubs.json') || File.exist?('stubs.json')
@@ -25,18 +27,28 @@ class Cuki
25
27
  configure_http_client
26
28
 
27
29
  action = args.first
30
+ if args.include?('--skip-autoformat')
31
+ args.delete_if { |arg| '--skip-autoformat' == arg }
32
+ @skip_autoformat = true
33
+ end
34
+ if args.include?('--skip-header')
35
+ args.delete_if { |arg| '--skip-header' == arg }
36
+ @skip_header = true
37
+ end
28
38
  if 'pull' == action
29
39
  configure_pull_stubs
30
40
  verify_project
31
41
  file = args[1]
32
42
  if file
33
43
  id = @config['mappings'].invert[file]
34
- raise "could not get id for #{file}"
44
+ raise "could not get id for #{file}" unless id
35
45
  pull_feature id, file
36
46
  else
37
- @config['mappings'].each { |id, filepath| pull_feature id, filepath }
47
+ Parallel.map(@config['mappings'], :in_processes => 4) do |id, filepath|
48
+ pull_feature id, filepath
49
+ end
38
50
  end
39
- #autoformat
51
+ autoformat
40
52
  elsif 'push' == action
41
53
  configure_push_stubs
42
54
  Pusher.push file, @config
@@ -51,7 +63,7 @@ class Cuki
51
63
  def verify_project
52
64
  # check features folder exists
53
65
  raise "features folder not found" unless File.exists?('features')
54
- #autoformat
66
+ autoformat
55
67
  end
56
68
 
57
69
  def read_config
@@ -72,35 +84,80 @@ class Cuki
72
84
 
73
85
  def pull_feature(id, filepath)
74
86
  @content = ''
75
- wiki_link = @config['host'] + '/pages/editpage.action?pageId=' + id.to_s
76
- puts "Downloading #{wiki_link}"
77
- response = @client.get wiki_link
87
+ wiki_edit_link = @config['host'] + '/pages/editpage.action?pageId=' + id.to_s
88
+ wiki_view_link = @config['host'] + '/pages/viewpage.action?pageId=' + id.to_s
89
+ puts "Downloading #{wiki_edit_link}"
90
+ response = @client.get wiki_edit_link
78
91
  doc = Nokogiri(response.body)
79
-
92
+
80
93
  unless doc.at('#content-title')
81
94
  puts "Not a valid confluence page:"
82
95
  puts doc.to_s
83
96
  exit(1)
84
97
  end
85
98
 
86
- @content += "Feature: " + doc.at('#content-title')[:value] + "\n\n"
87
- @content += "#{wiki_link}\n\n"
88
- @content += CGI.unescapeHTML(doc.css('#markupTextarea').text)
99
+ if @config['container']
100
+ handle_multi doc, id
101
+ else
102
+
103
+ @content += "Feature: " + doc.at('#content-title')[:value] + "\n\n"
104
+ @content += "#{wiki_view_link}\n\n"
105
+ @content += get_markup(doc)
89
106
 
90
- clean
107
+ clean
91
108
 
92
- process_tags
109
+ process_tags
93
110
 
94
- save_file filepath
111
+ @content = "# Generated by Cuki (#{Time.now})\n" + @content unless @skip_header
112
+
113
+ save_file filepath
114
+ end
95
115
  end
96
116
 
97
117
  def autoformat
98
- `cucumber -a . --dry-run -P` unless ENV['SKIP_AUTOFORMAT']
118
+ `cucumber -a . --dry-run -P` unless @skip_autoformat
119
+ end
120
+
121
+ def handle_multi doc, id
122
+ feature_title_compressed = doc.at('#content-title')[:value].anchorize
123
+
124
+ @content += get_markup(doc)
125
+ acceptance_criteria_matches = @content.match(@config['container'])
126
+ unless acceptance_criteria_matches
127
+ puts "Could not match #{config['container']}"
128
+ exit(1)
129
+ end
130
+ acceptance_criteria = acceptance_criteria_matches[1]
131
+ scenario_titles = acceptance_criteria.scan(/h2. (.*)/).flatten
132
+ scenario_blocks = acceptance_criteria.split(/h2. .*/)
133
+ scenario_blocks.shift
134
+
135
+ combined = {}
136
+ scenario_titles.each_with_index do |title, index|
137
+ combined[title] = scenario_blocks[index].gsub(/h6. (.*)/, '\1')
138
+ end
139
+ combined.each do |title, content|
140
+ scenario_title_compressed = title.anchorize
141
+ feature_filename = title.parameterize
142
+
143
+ dirpath = @config['mappings'][id]
144
+
145
+ FileUtils.mkdir_p(dirpath)
146
+
147
+ fname = "#{dirpath}/#{feature_filename.gsub("\r", '')}.feature"
148
+ File.open(fname, 'w') do |f|
149
+ puts "Writing #{fname}"
150
+ f.write "Feature: #{title}\n\n"
151
+ link = @config['host'] + "/pages/viewpage.action?pageId=#{id}##{feature_title_compressed}-#{scenario_title_compressed}"
152
+ f.write "\n\n" + link
153
+ f.write content
154
+ end
155
+ end
99
156
  end
100
157
 
101
158
  def clean
102
159
 
103
- @content.gsub('&nbsp;', '')
160
+ @content.gsub!('&nbsp;', '')
104
161
 
105
162
  # remove the double pipes used for table headers in Confluence
106
163
  @content.gsub!('||', '|')
@@ -113,6 +170,13 @@ class Cuki
113
170
  # remove any unwanted headers
114
171
  @content.gsub!(/h\d\. (Scenario: .*)/, '\1')
115
172
  @content.gsub!(/h\d\. (Scenario Outline: .*)/, '\1')
173
+ @content.gsub!(/h\d\. (Background: .*)/, '\1')
174
+
175
+ #Remove fancy quotes
176
+ @content.gsub!('’', "'")
177
+ @content.gsub!('‘', "'")
178
+ @content.gsub!('“', '"')
179
+ @content.gsub!('”', '"')
116
180
 
117
181
  end
118
182
 
@@ -134,7 +198,7 @@ class Cuki
134
198
  def save_file(filepath)
135
199
  dir_path = File.dirname(filepath)
136
200
 
137
- Dir.mkdir(dir_path) unless File.exists?(dir_path)
201
+ FileUtils.mkdir_p(dir_path) unless File.exists?(dir_path)
138
202
 
139
203
  File.open(filepath, 'w') do |f|
140
204
  puts "Writing #{filepath}"
@@ -172,4 +236,8 @@ class Cuki
172
236
  end
173
237
  end
174
238
 
239
+ def get_markup(doc)
240
+ CGI.unescapeHTML(doc.css('#markupTextarea').text)
241
+ end
242
+
175
243
  end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def anchorize
3
+ CGI.escape(self.gsub(' ', '').gsub("\r", ''))
4
+ end
5
+
6
+ def parameterize
7
+ self.downcase.gsub(' ', '_')
8
+ end
9
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuki
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 7
10
+ version: 0.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Waite
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-16 00:00:00 Z
18
+ date: 2011-10-17 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -56,11 +56,25 @@ dependencies:
56
56
  - 0
57
57
  version: "0"
58
58
  version_requirements: *id003
59
+ name: parallel
60
+ prerelease: false
61
+ type: :runtime
62
+ - !ruby/object:Gem::Dependency
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ version_requirements: *id004
59
73
  name: shoulda
60
74
  prerelease: false
61
75
  type: :development
62
76
  - !ruby/object:Gem::Dependency
63
- requirement: &id004 !ruby/object:Gem::Requirement
77
+ requirement: &id005 !ruby/object:Gem::Requirement
64
78
  none: false
65
79
  requirements:
66
80
  - - ~>
@@ -71,12 +85,12 @@ dependencies:
71
85
  - 0
72
86
  - 0
73
87
  version: 1.0.0
74
- version_requirements: *id004
88
+ version_requirements: *id005
75
89
  name: bundler
76
90
  prerelease: false
77
91
  type: :development
78
92
  - !ruby/object:Gem::Dependency
79
- requirement: &id005 !ruby/object:Gem::Requirement
93
+ requirement: &id006 !ruby/object:Gem::Requirement
80
94
  none: false
81
95
  requirements:
82
96
  - - ~>
@@ -87,12 +101,12 @@ dependencies:
87
101
  - 6
88
102
  - 4
89
103
  version: 1.6.4
90
- version_requirements: *id005
104
+ version_requirements: *id006
91
105
  name: jeweler
92
106
  prerelease: false
93
107
  type: :development
94
108
  - !ruby/object:Gem::Dependency
95
- requirement: &id006 !ruby/object:Gem::Requirement
109
+ requirement: &id007 !ruby/object:Gem::Requirement
96
110
  none: false
97
111
  requirements:
98
112
  - - ">="
@@ -101,12 +115,12 @@ dependencies:
101
115
  segments:
102
116
  - 0
103
117
  version: "0"
104
- version_requirements: *id006
118
+ version_requirements: *id007
105
119
  name: rcov
106
120
  prerelease: false
107
121
  type: :development
108
122
  - !ruby/object:Gem::Dependency
109
- requirement: &id007 !ruby/object:Gem::Requirement
123
+ requirement: &id008 !ruby/object:Gem::Requirement
110
124
  none: false
111
125
  requirements:
112
126
  - - ">="
@@ -115,7 +129,7 @@ dependencies:
115
129
  segments:
116
130
  - 0
117
131
  version: "0"
118
- version_requirements: *id007
132
+ version_requirements: *id008
119
133
  name: rspec
120
134
  prerelease: false
121
135
  type: :development
@@ -139,10 +153,12 @@ files:
139
153
  - Rakefile
140
154
  - VERSION
141
155
  - bin/cuki
156
+ - cucumber.yml
142
157
  - cuki.gemspec
143
158
  - cuki.yaml.sample
144
159
  - features/pull/pull.feature
145
160
  - features/pull/pull_single.feature
161
+ - features/pull/splitting.feature
146
162
  - features/pull/tables.feature
147
163
  - features/pull/tags.feature
148
164
  - features/pull/textile.feature
@@ -154,6 +170,7 @@ files:
154
170
  - features/support/env.rb
155
171
  - lib/cuki.rb
156
172
  - lib/pusher.rb
173
+ - lib/string_utils.rb
157
174
  - spec/cuki_spec.rb
158
175
  - spec/spec_helper.rb
159
176
  homepage: http://github.com/andyw8/cuki