cuki 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,52 +1,42 @@
1
1
  = Overview
2
2
 
3
- Cuki provides an easy way to import acceptance criteria from a Confluence wiki into Cucumber feature files
4
-
5
- - Converts Confluence tables to Cucumber tables
6
- - Strips out unnecessary Confluence formatting (headers, etc.)
7
- - Includes a link back to the original Confluence page
8
- - Formats the feature using Cucumber's auto-formatter (optional)
9
- - Support client SSL certificates for use within an organisation's secure intranet
10
-
11
- It can be used as part of a CI process or just for ad-hoc imports.
3
+ Cuki provides an easy way to import acceptance criteria from a Confluence wiki into Cucumber feature files. It can be used as part of a CI process or just for ad-hoc imports.
12
4
 
13
5
  == Installation
14
6
 
15
- Require the gem in your Gemfile:
7
+ gem install cuki
16
8
 
17
- gem 'cuki'
9
+ (or use Bundler)
18
10
 
19
11
  == Setup
20
12
 
21
13
  Cuki expects a configuration file in config/cuki.yml. See the sample provided.
22
14
 
23
- You can have a one-to-one association between Confluences pages, or you can split a single Confluence
24
- pages into multiple features. The splitter is a little fussy about structure, it must be:
15
+ A single Confluence page maps to one or more features. The page should contain the structure:
25
16
 
26
17
  h1. Acceptance Criteria
27
-
18
+
28
19
  h2. Feature Name
29
-
20
+
21
+ Scenario: ...
22
+
30
23
  h2. Another Feature Name
31
24
 
25
+ Scenario: ...
26
+
32
27
  == Usage
33
28
 
34
29
  Run it from the command line:
35
30
 
36
- bundle exec cuki pull
37
-
38
- or, if using binstubs:
39
-
40
- bin/cuki pull
31
+ cuki pull
41
32
 
42
- You can also pull a single feature:
33
+ You can also pull from a particular Confluence page:
43
34
 
44
- cuki pull features/add_product.feature
35
+ cuki pull features/products
45
36
 
46
37
  == Tags
47
38
 
48
- You can add tags to a feature based on the wiki page content. See the sample configuration file.
49
-
39
+ You can add tags to a feature based on the wiki page markup. See the sample configuration file.
50
40
 
51
41
  == Options
52
42
 
@@ -54,23 +44,25 @@ You can add tags to a feature based on the wiki page content. See the sample con
54
44
 
55
45
  == Configuration
56
46
 
57
- If your Confluence installation requires a client certificate, you can supply the paths for these:
47
+ If your Confluence installation requires a client certificate, you can supply the paths for these as environment variables:
58
48
 
59
- - CER=/path/to/ca.pem.cer
60
- - PEM=/path/to/something.pem
49
+ CER=/path/to/ca.pem.cer PEM=/path/to/something.pem cuki pull
61
50
 
62
51
  == Known Issues and Limitations
63
52
 
64
53
  - Will only work with Confluence setups which have no password, or use client certificates for authentication
65
- - Only provides one-way sync, i.e. you can't edit a file locally and push it to Confluence
54
+ - Expects a two level hierarchy, with folders used for epics/themes, containing one or more feature files
66
55
 
67
- == TODO
56
+ == Bugs and To Do
68
57
 
69
- - Handle links
70
- - Support for pushing features to Confluence (roundtrip editing)
58
+ - Should exit before importing features if the current features aren't valid syntax
59
+
60
+ == Future Plans
61
+
62
+ - Add roundtrip editing, i.e. edit a file locally and push it to Confluence
63
+ - Some way to update the wiki to indicate which scenarios are passing, failing or not yet implemented
71
64
 
72
65
  == Copyright
73
66
 
74
67
  Copyright (c) 2011 Andy Waite. See LICENSE.txt for
75
68
  further details.
76
-
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.0.12
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cuki"
8
- s.version = "0.0.11"
8
+ s.version = "0.0.12"
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-23"
12
+ s.date = "2011-10-25"
13
13
  s.description = ""
14
14
  s.email = "andy@andywaite.com"
15
15
  s.executables = ["cuki"]
@@ -34,7 +34,6 @@ Gem::Specification.new do |s|
34
34
  "features/pull/error_handling.feature",
35
35
  "features/pull/pull.feature",
36
36
  "features/pull/pull_single.feature",
37
- "features/pull/splitting.feature",
38
37
  "features/pull/tables.feature",
39
38
  "features/pull/tags.feature",
40
39
  "features/pull/textile.feature",
@@ -1,5 +1,5 @@
1
- # edit this and save it as config/cuki.yaml
2
- # the mappings associate the page IDs on Confluence with local feature files
1
+ # edit this file and save it as config/cuki.yaml
2
+ # each mapping associates a Confluence page with a folder containing one or more feature files
3
3
  ---
4
4
  host: http://mywiki
5
5
  container: "h1. Acceptance Criteria"
@@ -1,56 +1,142 @@
1
- # Feature: Pull
2
- #
3
- # @focus @announc
4
- # Scenario: Pull all features
5
- # Given a file named "config/cuki.yaml" with:
6
- # """
7
- # ---
8
- # host: http://example.com
9
- # mappings:
10
- # 123: features/products/add_product.feature
11
- # 456: features/products/remove_product.feature
12
- # """
13
- # And a Confluence page on "example.com" with id 123:
14
- # """
15
- # <input id="content-title" value="Add Product">
16
- # <div id="markupTextarea">
17
- # This feature describes adding a product
18
- #
19
- # # Some comment
20
- #
21
- # Blah
22
- # </div>
23
- # """
24
- # And a Confluence page on "example.com" with id 456:
25
- # """
26
- # <input id="content-title" value="Remove Product">
27
- # <div id="markupTextarea">
28
- # This feature describes removing a product
29
- # </div>
30
- # """
31
- # When I run `cuki pull --skip-autoformat`
32
- # Then the file "features/products/add_product.feature" should contain exactly:
33
- # """
34
- # Feature: Add Product
35
- #
36
- # http://example.com/pages/viewpage.action?pageId=123
37
- #
38
- #
39
- # This feature describes adding a product
40
- #
41
- # - Some comment
42
- #
43
- # Blah
44
- #
45
- # """
46
- # And the file "features/products/remove_product.feature" should contain exactly:
47
- # """
48
- # Feature: Remove Product
49
- #
50
- # http://example.com/pages/viewpage.action?pageId=456
51
- #
52
- #
53
- # This feature describes removing a product
54
- #
55
- # """
56
- #
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
+ Scenario: Pull all features (default container)
6
+ Given a file named "config/cuki.yaml" with:
7
+ """
8
+ ---
9
+ host: http://example.com
10
+ mappings:
11
+ 123: features/products
12
+ """
13
+ And a Confluence page on "example.com" with id 123:
14
+ """
15
+ <input id="content-title" value="Product Management">
16
+ <div id="markupTextarea">
17
+ Pretext
18
+
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`
39
+ Then the file "features/products/add_product.feature" should contain exactly:
40
+ """
41
+ Feature: Add Product
42
+
43
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
44
+
45
+ This feature describes adding a product
46
+
47
+ Scenario: Scenario A
48
+
49
+
50
+ """
51
+ And the file "features/products/remove_product.feature" should contain exactly:
52
+ """
53
+ Feature: Remove Product
54
+
55
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-RemoveProduct
56
+
57
+ This feature describes removing a product
58
+
59
+ Scenario Outline: Scenario B
60
+
61
+
62
+ """
63
+
64
+ Scenario: Pull all features (specified container)
65
+ Given a file named "config/cuki.yaml" with:
66
+ """
67
+ ---
68
+ host: http://example.com
69
+ container: !ruby/regexp '/h1\. \*Acceptance Criteria\*/'
70
+ mappings:
71
+ 123: features/products
72
+ """
73
+ And a Confluence page on "example.com" with id 123:
74
+ """
75
+ <input id="content-title" value="Product Management">
76
+ <div id="markupTextarea">
77
+ h1. *Acceptance Criteria*
78
+
79
+ Something
80
+
81
+ h2. Add Product
82
+
83
+ This feature describes adding a product
84
+
85
+ h6. Scenario: Scenario A
86
+
87
+ h1. Next Section
88
+ </div>
89
+ """
90
+ When I run `cuki pull --skip-autoformat`
91
+ Then the file "features/products/add_product.feature" should contain exactly:
92
+ """
93
+ Feature: Add Product
94
+
95
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
96
+
97
+ This feature describes adding a product
98
+
99
+ Scenario: Scenario A
100
+
101
+
102
+ """
103
+
104
+ Scenario: Special Chars
105
+ Given a file named "config/cuki.yaml" with:
106
+ """
107
+ ---
108
+ host: http://example.com
109
+ mappings:
110
+ 123: features/products
111
+ """
112
+ And a Confluence page on "example.com" with id 123:
113
+ """
114
+ <input id="content-title" value="Product Management">
115
+ <div id="markupTextarea">
116
+ h1. Acceptance Criteria
117
+
118
+ Something
119
+
120
+ h2. Add/Remove Product
121
+
122
+ This feature describes adding a product
123
+
124
+ h6. Scenario: Scenario A
125
+
126
+ h1. Next Section
127
+ </div>
128
+ """
129
+ When I run `cuki pull --skip-autoformat`
130
+ Then the file "features/products/add_remove_product.feature" should contain exactly:
131
+ """
132
+ Feature: Add/Remove Product
133
+
134
+ http://example.com/pages/viewpage.action?pageId=123#ProductManagement-Add%2FRemoveProduct
135
+
136
+ This feature describes adding a product
137
+
138
+ Scenario: Scenario A
139
+
140
+
141
+ """
142
+
@@ -1,6 +1,5 @@
1
1
  Feature: Pull single
2
2
 
3
- @focus @announce
4
3
  Scenario: Pull single feature
5
4
  Given a file named "config/cuki.yaml" with:
6
5
  """
@@ -1,5 +1,6 @@
1
1
  Feature: Tags
2
2
 
3
+ @announce
3
4
  Scenario:
4
5
  Given a file named "config/cuki.yaml" with:
5
6
  """
@@ -7,7 +8,8 @@ Feature: Tags
7
8
  host: http://example.com
8
9
  tags:
9
10
  draft: "{info:title=Draft version}"
10
- signed_off: "{info:title=Signed-off}"
11
+ pending: "{info:title=Pending}"
12
+ another: "{info:title=Another}"
11
13
  mappings:
12
14
  123: features/products
13
15
  """
@@ -16,11 +18,13 @@ Feature: Tags
16
18
  <input id="content-title" value="Products">
17
19
  <div id="markupTextarea">
18
20
  h1. Acceptance Criteria
19
-
20
21
  {info:title=Draft version}
21
22
 
22
23
  h2. Add Product
23
24
 
25
+ {info:title=Pending}
26
+ {info:title=Another}
27
+
24
28
  h6. Scenario: Foo
25
29
  </div>
26
30
  """
@@ -32,6 +36,11 @@ Feature: Tags
32
36
 
33
37
  http://example.com/pages/viewpage.action?pageId=123#Products-AddProduct
34
38
 
39
+ @pending
40
+
41
+ @another
42
+
43
+
35
44
  Scenario: Foo
36
45
 
37
46
  """
@@ -13,7 +13,7 @@ class ConfluencePage
13
13
  def content
14
14
  content = CGI.unescapeHTML @doc.css('#markupTextarea').text
15
15
 
16
- content.gsub!('&nbsp;', '')
16
+ content.gsub!('&nbsp;', ' ')
17
17
 
18
18
  # remove the double pipes used for table headers in Confluence
19
19
  content.gsub!('||', '|')
@@ -54,7 +54,9 @@ class Cuki
54
54
 
55
55
  def verify_project
56
56
  terminate "features folder not found" unless File.exists?('features')
57
+ puts "Verifying existing features"
57
58
  `cucumber --dry-run -P`
59
+ terminate "Validation of existing features failed" unless 0 == $?
58
60
  end
59
61
 
60
62
  def read_config
@@ -82,17 +84,21 @@ class Cuki
82
84
  end
83
85
 
84
86
  def autoformat!
85
- `cucumber -a . --dry-run -P` unless @skip_autoformat
87
+ unless @skip_autoformat
88
+ `cucumber -a . --dry-run -P`
89
+ puts "Running autoformat"
90
+ end
86
91
  end
87
92
 
88
93
  def handle_multi response_body, id
89
94
  confluence_page = ConfluencePage.new(response_body)
90
95
 
91
- content = confluence_page.content
96
+ full_content = confluence_page.content
92
97
 
93
- terminate "Could not find acceptance criteria container" unless content.match(container)
98
+ terminate "Could not find acceptance criteria container" unless full_content.match(container)
94
99
 
95
- acceptance_criteria = content.split(container).last
100
+ acceptance_criteria = full_content.split(container).last
101
+
96
102
  if acceptance_criteria.include?(PRIMARY_HEADER)
97
103
  acceptance_criteria = acceptance_criteria.split(/#{PRIMARY_HEADER}/).first
98
104
  end
@@ -103,14 +109,15 @@ class Cuki
103
109
  scenario_blocks = acceptance_criteria.split(/#{FEATURE_HEADER} .*/)
104
110
  scenario_blocks.shift
105
111
 
112
+ puts "Warning: No scenarios found in doc #{id}" if scenario_titles.empty?
113
+
114
+ pretext = acceptance_criteria.split(/#{FEATURE_HEADER}/).first
115
+
106
116
  combined = {}
107
- found = 0
108
117
  scenario_titles.each_with_index do |title, index|
109
- combined[title] = scenario_blocks[index].gsub(/#{SCENARIO_HEADER} (.*)/, '\1')
110
- found += 1
118
+ combined[title] = scenario_blocks[index].gsub(/h\d. ([Scenario|Scenario Outline].*)/, '\1')
111
119
  end
112
120
 
113
- terminate "No scenarios found in doc #{id}" if 0 == found
114
121
  combined.each do |title, content|
115
122
 
116
123
  feature_filename = title.parameterize
@@ -122,7 +129,12 @@ class Cuki
122
129
  File.open(fname, 'w') do |f|
123
130
  if @config['tags']
124
131
  @config['tags'].each do |tag, token|
125
- f.write "@#{tag}\n" if acceptance_criteria.include?(token)
132
+ f.write "@#{tag}\n" if pretext.include?(token)
133
+ end
134
+ end
135
+ if @config['tags']
136
+ @config['tags'].each do |tag, token|
137
+ content.gsub!(token, "@#{tag}\n")
126
138
  end
127
139
  end
128
140
  f.write "Feature: #{title}\n\n"
@@ -4,6 +4,6 @@ class String
4
4
  end
5
5
 
6
6
  def parameterize
7
- self.downcase.gsub(/[^a-z0-9\-]/, '_')
7
+ self.downcase.gsub(/[^a-z0-9\-\(\)]/, '_')
8
8
  end
9
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: 9
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 11
10
- version: 0.0.11
9
+ - 12
10
+ version: 0.0.12
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-23 00:00:00 Z
18
+ date: 2011-10-25 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -159,7 +159,6 @@ files:
159
159
  - features/pull/error_handling.feature
160
160
  - features/pull/pull.feature
161
161
  - features/pull/pull_single.feature
162
- - features/pull/splitting.feature
163
162
  - features/pull/tables.feature
164
163
  - features/pull/tags.feature
165
164
  - features/pull/textile.feature
@@ -1,145 +0,0 @@
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 (default container)
7
- Given a file named "config/cuki.yaml" with:
8
- """
9
- ---
10
- host: http://example.com
11
- mappings:
12
- 123: features/products
13
- """
14
- And a Confluence page on "example.com" with id 123:
15
- """
16
- <input id="content-title" value="Product Management">
17
- <div id="markupTextarea">
18
- Pretext
19
-
20
- h1. Acceptance Criteria
21
-
22
- Something
23
-
24
- h2. Add Product
25
-
26
- This feature describes adding a product
27
-
28
- h6. Scenario: Scenario A
29
-
30
- h2. Remove Product
31
-
32
- This feature describes removing a product
33
-
34
- h6. Scenario Outline: Scenario B
35
-
36
- h1. Next Section
37
- </div>
38
- """
39
- When I run `cuki pull --skip-autoformat`
40
- Then the file "features/products/add_product.feature" should contain exactly:
41
- """
42
- Feature: Add Product
43
-
44
- http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
45
-
46
- This feature describes adding a product
47
-
48
- Scenario: Scenario A
49
-
50
-
51
- """
52
- And the file "features/products/remove_product.feature" should contain exactly:
53
- """
54
- Feature: Remove Product
55
-
56
- http://example.com/pages/viewpage.action?pageId=123#ProductManagement-RemoveProduct
57
-
58
- This feature describes removing a product
59
-
60
- Scenario Outline: Scenario B
61
-
62
-
63
- """
64
-
65
- @announce
66
- Scenario: Pull all features (specified container)
67
- Given a file named "config/cuki.yaml" with:
68
- """
69
- ---
70
- host: http://example.com
71
- container: !ruby/regexp '/h1\. \*Acceptance Criteria\*/'
72
- mappings:
73
- 123: features/products
74
- """
75
- And a Confluence page on "example.com" with id 123:
76
- """
77
- <input id="content-title" value="Product Management">
78
- <div id="markupTextarea">
79
- h1. *Acceptance Criteria*
80
-
81
- Something
82
-
83
- h2. Add Product
84
-
85
- This feature describes adding a product
86
-
87
- h6. Scenario: Scenario A
88
-
89
- h1. Next Section
90
- </div>
91
- """
92
- When I run `cuki pull --skip-autoformat`
93
- Then the file "features/products/add_product.feature" should contain exactly:
94
- """
95
- Feature: Add Product
96
-
97
- http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
98
-
99
- This feature describes adding a product
100
-
101
- Scenario: Scenario A
102
-
103
-
104
- """
105
-
106
- @announce
107
- Scenario: Special Chars
108
- Given a file named "config/cuki.yaml" with:
109
- """
110
- ---
111
- host: http://example.com
112
- mappings:
113
- 123: features/products
114
- """
115
- And a Confluence page on "example.com" with id 123:
116
- """
117
- <input id="content-title" value="Product Management">
118
- <div id="markupTextarea">
119
- h1. Acceptance Criteria
120
-
121
- Something
122
-
123
- h2. Add/Remove Product
124
-
125
- This feature describes adding a product
126
-
127
- h6. Scenario: Scenario A
128
-
129
- h1. Next Section
130
- </div>
131
- """
132
- When I run `cuki pull --skip-autoformat`
133
- Then the file "features/products/add_remove_product.feature" should contain exactly:
134
- """
135
- Feature: Add/Remove Product
136
-
137
- http://example.com/pages/viewpage.action?pageId=123#ProductManagement-Add%2FRemoveProduct
138
-
139
- This feature describes adding a product
140
-
141
- Scenario: Scenario A
142
-
143
-
144
- """
145
-