gitnesse 0.1.3 → 0.12.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 +15 -9
- data/bin/gitnesse +5 -3
- data/lib/gitnesse.rb +48 -247
- data/lib/gitnesse/configuration.rb +54 -0
- data/lib/gitnesse/dependencies.rb +38 -0
- data/lib/gitnesse/features.rb +38 -0
- data/lib/gitnesse/git_config.rb +39 -0
- data/lib/gitnesse/hooks.rb +50 -0
- data/lib/gitnesse/railtie.rb +2 -2
- data/lib/gitnesse/support/hook.rb +11 -0
- data/lib/gitnesse/tasks.rake +12 -6
- data/lib/gitnesse/version.rb +1 -1
- data/lib/gitnesse/wiki.rb +173 -0
- data/test/lib/gitnesse/build_page_content_test.rb +12 -3
- data/test/lib/gitnesse/commit_info_test.rb +8 -20
- data/test/lib/gitnesse/{config_to_hash_test.rb → configuration_to_hash_test.rb} +8 -7
- data/test/lib/gitnesse/custom_branch_test.rb +8 -9
- data/test/lib/gitnesse/dependencies_check_test.rb +60 -0
- data/test/lib/gitnesse/extract_features_test.rb +2 -2
- data/test/lib/gitnesse/{gather_features_test.rb → gather_test.rb} +6 -6
- data/test/lib/gitnesse/load_feature_files_into_wiki_test.rb +1 -1
- data/test/lib/gitnesse/read_git_config_test.rb +9 -11
- data/test/lib/gitnesse/strip_results_test.rb +52 -0
- data/test/lib/gitnesse/write_file_test.rb +18 -0
- metadata +21 -12
- data/test/lib/gitnesse/check_dependencies_test.rb +0 -45
- data/test/lib/gitnesse/write_feature_file_test.rb +0 -18
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gitnesse
|
2
|
+
class Dependencies
|
3
|
+
class NoGitError < StandardError ; end
|
4
|
+
class NoCucumberError < StandardError ; end
|
5
|
+
class NoRepositoryURLError < StandardError ; end
|
6
|
+
class NoAnnotationInfoError < StandardError ; end
|
7
|
+
|
8
|
+
# Checks Gitnesse's dependencies, and throws an error if one of them is
|
9
|
+
# missing.
|
10
|
+
def self.check
|
11
|
+
check_git
|
12
|
+
check_cucumber
|
13
|
+
check_repository_url
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def self.check_git
|
19
|
+
raise NoGitError, "git not found or not working." unless Kernel.system("git --version")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.check_cucumber
|
23
|
+
raise NoCucumberError, "cucumber not found or not working." unless Kernel.system("cucumber --version")
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.check_repository_url
|
27
|
+
raise NoRepositoryURLError, "You must select a repository_url to run Gitnesse." if Gitnesse.configuration.repository_url.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.check_annotation_info
|
31
|
+
if Gitnesse.configuration.annotate_results
|
32
|
+
if Gitnesse.configuration.info.nil?
|
33
|
+
raise NoAnnotationInfoError, "You must enter local information to annotate test results in the wiki"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gitnesse
|
2
|
+
class Features
|
3
|
+
|
4
|
+
# Public: Writes a feature to disk, given the filename and the
|
5
|
+
# features.
|
6
|
+
#
|
7
|
+
# filename - the filename to use for the feature
|
8
|
+
# features - the features to write to disk
|
9
|
+
#
|
10
|
+
def self.write_file(filename, features)
|
11
|
+
File.open(filename, "w") do |file|
|
12
|
+
file.write(gather(features))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Gathers features for placing into files. Currently only supports
|
17
|
+
# one feature per page. Others are discarded
|
18
|
+
#
|
19
|
+
# page_features - the features
|
20
|
+
#
|
21
|
+
# Returns a string containing the
|
22
|
+
def self.gather(page_features)
|
23
|
+
return '' if page_features.nil? || page_features.empty?
|
24
|
+
|
25
|
+
features = ''
|
26
|
+
|
27
|
+
name, content = page_features.shift
|
28
|
+
puts " # Pulling Feature: #{name}"
|
29
|
+
features += content
|
30
|
+
|
31
|
+
page_features.each do |name, feature|
|
32
|
+
puts " # WARNING! Discarding Feature: #{name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
features
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Gitnesse
|
2
|
+
class GitConfig
|
3
|
+
class NoValueSetError < StandardError ; end
|
4
|
+
|
5
|
+
# Public: Reads a value from the system's git config.
|
6
|
+
#
|
7
|
+
# key - the value to look up from the git config
|
8
|
+
#
|
9
|
+
# Returns a string containing the git config value or GitConfigNotFoundError
|
10
|
+
def self.read(key)
|
11
|
+
value = get_from_git_config key
|
12
|
+
|
13
|
+
if value.empty? || value == ''
|
14
|
+
raise NoValueSetError, "Cannot read git config value for #{key}"
|
15
|
+
end
|
16
|
+
|
17
|
+
value
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Private: Tries to fetch a value using git config --get
|
23
|
+
#
|
24
|
+
# key - the value to look up from the git config
|
25
|
+
#
|
26
|
+
# Returns a string containing the value supplied by git
|
27
|
+
def self.get_from_git_config(key)
|
28
|
+
value = ''
|
29
|
+
|
30
|
+
value = `git config --get #{key}`
|
31
|
+
|
32
|
+
if value.empty? || value == ''
|
33
|
+
value = `git config --get --global #{key}`
|
34
|
+
end
|
35
|
+
|
36
|
+
value.strip
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Gitnesse
|
2
|
+
class Hooks
|
3
|
+
@dir = File.join(Dir.home, ".gitnesse")
|
4
|
+
|
5
|
+
# Public: Sets up ~/.gitnesse for appending scenario results
|
6
|
+
#
|
7
|
+
# Returns nothing
|
8
|
+
def self.setup
|
9
|
+
Gitnesse::Configuration.load_using_search
|
10
|
+
FileUtils.rm_rf(@dir) if File.directory?(@dir)
|
11
|
+
Dir.mkdir(@dir)
|
12
|
+
`git clone #{Gitnesse.configuration.repository_url} #{@dir}`
|
13
|
+
Wiki.new(@dir).remove_past_results
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Removes ~/.gitnesse after all cukes are run
|
17
|
+
#
|
18
|
+
# Returns nothing
|
19
|
+
def self.teardown
|
20
|
+
Dir.chdir(@dir) do
|
21
|
+
`git push origin master`
|
22
|
+
end
|
23
|
+
|
24
|
+
FileUtils.rm_rf(@dir)
|
25
|
+
FileUtils.rm(File.absolute_path("#{Gitnesse.configuration.target_directory}/support/gitnesse_hooks.rb"))
|
26
|
+
end
|
27
|
+
|
28
|
+
# Public: Adds hooks into Cucumber
|
29
|
+
#
|
30
|
+
# Returns nothing
|
31
|
+
def self.create
|
32
|
+
hook_file = File.join(File.dirname(__FILE__), "support/hook.rb")
|
33
|
+
support_dir = File.absolute_path("#{Gitnesse.configuration.target_directory}/support")
|
34
|
+
target_file = File.join(support_dir, "gitnesse_hooks.rb")
|
35
|
+
|
36
|
+
Dir.mkdir(support_dir) unless File.directory?(support_dir)
|
37
|
+
|
38
|
+
File.write(target_file, File.read(hook_file))
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Appends scenario results to relevant page in wiki
|
42
|
+
#
|
43
|
+
# scenario - the scenario results from Cucumber
|
44
|
+
#
|
45
|
+
# Returns nothing
|
46
|
+
def self.append_to_wiki(scenario)
|
47
|
+
Wiki.new(@dir).append_results(scenario)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/gitnesse/railtie.rb
CHANGED
data/lib/gitnesse/tasks.rake
CHANGED
@@ -4,25 +4,31 @@ namespace :gitnesse do
|
|
4
4
|
|
5
5
|
desc "Pull features from remote repository and run cucumber."
|
6
6
|
task :run => :environment do
|
7
|
-
Gitnesse.
|
7
|
+
Gitnesse::Configuration.load_using_search
|
8
8
|
Gitnesse.run
|
9
9
|
end
|
10
10
|
|
11
11
|
desc "Pull features from remote git wiki repository."
|
12
12
|
task :pull => :environment do
|
13
|
-
Gitnesse.
|
13
|
+
Gitnesse::Configuration.load_using_search
|
14
14
|
Gitnesse.pull
|
15
15
|
end
|
16
16
|
|
17
17
|
desc "Push features to remote git wiki repository."
|
18
18
|
task :push => :environment do
|
19
|
-
Gitnesse.
|
19
|
+
Gitnesse::Configuration.load_using_search
|
20
20
|
Gitnesse.push
|
21
21
|
end
|
22
22
|
|
23
|
+
desc "Push features to remote git wiki repository, run cucumber, and push results to wiki"
|
24
|
+
task :push => :environment do
|
25
|
+
Gitnesse::Configuration.load_using_search
|
26
|
+
Gitnesse.push_results
|
27
|
+
end
|
28
|
+
|
23
29
|
desc "Dump the current config info to the console."
|
24
30
|
task :info => :environment do
|
25
|
-
Gitnesse.
|
26
|
-
puts Gitnesse.
|
31
|
+
Gitnesse::Configuration.load_using_search
|
32
|
+
puts Gitnesse.configuration.to_yaml
|
27
33
|
end
|
28
|
-
end
|
34
|
+
end
|
data/lib/gitnesse/version.rb
CHANGED
@@ -0,0 +1,173 @@
|
|
1
|
+
module Gitnesse
|
2
|
+
class Wiki
|
3
|
+
attr_accessor :wiki
|
4
|
+
|
5
|
+
def initialize(dir = Dir.mktmpdir)
|
6
|
+
@wiki = Gollum::Wiki.new(dir)
|
7
|
+
@commit_info = Gitnesse.generate_commit_info
|
8
|
+
end
|
9
|
+
|
10
|
+
# Public: Loads the provided feature files into the wiki
|
11
|
+
#
|
12
|
+
# feature_files - a collection of files to search for features
|
13
|
+
# e.g. Dir.glob("./features/**/*.feature")
|
14
|
+
#
|
15
|
+
def load_feature_files(feature_files)
|
16
|
+
return if feature_files.nil?
|
17
|
+
|
18
|
+
feature_files.each do |feature_file|
|
19
|
+
feature_name = File.basename(feature_file, ".feature")
|
20
|
+
feature_content = File.read(feature_file)
|
21
|
+
wiki_page = @wiki.page(feature_name)
|
22
|
+
wiki_page ||= @wiki.page("#{feature_name}.feature")
|
23
|
+
|
24
|
+
if wiki_page
|
25
|
+
update_wiki_page(wiki_page, feature_name, feature_content)
|
26
|
+
else
|
27
|
+
create_wiki_page(feature_name, feature_content)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Returns the Wiki's pages
|
33
|
+
#
|
34
|
+
# Returns an array of Wiki pages
|
35
|
+
def pages
|
36
|
+
@wiki.pages
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Extracts gherkins from wiki page
|
40
|
+
#
|
41
|
+
# page - Wiki page to get features from
|
42
|
+
#
|
43
|
+
# Returns a hash of Cucumber features
|
44
|
+
def self.extract_features(page)
|
45
|
+
data = page.respond_to?(:raw_data) ? page.raw_data : page
|
46
|
+
features = {}
|
47
|
+
|
48
|
+
if match_result = data.match(/\u0060{3}gherkin(.+)\u0060{3}/m)
|
49
|
+
captures = match_result.captures
|
50
|
+
|
51
|
+
# create hash with feature name as key and feature text as value
|
52
|
+
captures.each do |capture|
|
53
|
+
feature_definition_at = capture.index('Feature:')
|
54
|
+
feature_text = capture[feature_definition_at,capture.size-1]
|
55
|
+
feature_lines = feature_text.split("\n")
|
56
|
+
feature_definition = feature_lines.grep(/^Feature:/).first
|
57
|
+
|
58
|
+
if feature_definition
|
59
|
+
feature_name = feature_definition.split(":").last.strip.gsub(" ","-").downcase
|
60
|
+
features[feature_name] = feature_text
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
features
|
66
|
+
end
|
67
|
+
|
68
|
+
# Public: Builds wiki page content
|
69
|
+
#
|
70
|
+
# feature_content - Content to generate the page content from
|
71
|
+
# old_page_content - old page content to replace with new page content
|
72
|
+
#
|
73
|
+
# Returns a string containing the generated page content
|
74
|
+
def build_page_content(feature_content, old_page_content = nil)
|
75
|
+
content = "```gherkin\n#{feature_content}\n```"
|
76
|
+
return content if old_page_content.nil? || old_page_content.empty?
|
77
|
+
|
78
|
+
features = Wiki.extract_features(old_page_content)
|
79
|
+
|
80
|
+
_, old_feature_content = features.shift
|
81
|
+
old_page_content.sub(old_feature_content, feature_content)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Public: Removes past Cucumber results from feature files
|
85
|
+
#
|
86
|
+
# Returns nothing
|
87
|
+
def remove_past_results
|
88
|
+
@commit_info[:message] = Gitnesse.configuration.info
|
89
|
+
features = Dir.glob("#{Gitnesse.configuration.target_directory}/*.feature")
|
90
|
+
|
91
|
+
features.each do |feature|
|
92
|
+
feature_name = File.basename(feature, ".feature")
|
93
|
+
page = @wiki.page(feature_name) || @wiki.page("#{feature_name}.feature")
|
94
|
+
|
95
|
+
if page
|
96
|
+
content = page.raw_data
|
97
|
+
content = strip_results(content)
|
98
|
+
@wiki.update_page(page, page.name, :markdown, content, @commit_info)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Public: Strips old cucumber results
|
104
|
+
#
|
105
|
+
# content - the string to remote old results from
|
106
|
+
#
|
107
|
+
# Returns a string
|
108
|
+
def strip_results(content)
|
109
|
+
if content.match(/\u0060{3}gherkin.*\u0060{3}(.*)/m)[1]
|
110
|
+
[ "FAILED", "PASSED", "PENDING", "UNDEFINED" ].each do |type|
|
111
|
+
content.gsub!(/\n*\`Last result was #{type}: .*\n*/, '')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
content
|
115
|
+
end
|
116
|
+
|
117
|
+
# Public: Appends results of cucumber scenario to wiki
|
118
|
+
#
|
119
|
+
# scenario - Cucumber scenario from After hook
|
120
|
+
#
|
121
|
+
# Returns nothing
|
122
|
+
def append_results(scenario)
|
123
|
+
pages = @wiki.pages
|
124
|
+
filename = File.basename(scenario.feature.file, ".feature")
|
125
|
+
@commit_info[:message] = Gitnesse.configuration.info
|
126
|
+
|
127
|
+
pages.each do |page|
|
128
|
+
if page.name == filename || page.name == "#{filename}.feature"
|
129
|
+
if page.text_data.include? scenario.name
|
130
|
+
content = page.raw_data
|
131
|
+
string = "\n\`Last result was #{scenario.status.to_s.upcase}: #{scenario.name} (#{Time.now.to_s} - #{Gitnesse.configuration.info})\`\n"
|
132
|
+
content.gsub(string, '')
|
133
|
+
content << string
|
134
|
+
@wiki.update_page(page, page.name, :markdown, content, @commit_info)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# Private: Creates a new wiki page for the provided name and content
|
143
|
+
#
|
144
|
+
# name - the name of the page to create
|
145
|
+
# content - the content the page should have
|
146
|
+
#
|
147
|
+
# Returns the newly created wiki page
|
148
|
+
def create_wiki_page(name, content)
|
149
|
+
new_page_content = build_page_content(content)
|
150
|
+
@wiki.write_page(name, :markdown, new_page_content, @commit_info)
|
151
|
+
puts " # Created Page: #{name}"
|
152
|
+
end
|
153
|
+
|
154
|
+
# Private: Updates a wiki page with the provided name and content
|
155
|
+
#
|
156
|
+
# wiki_page - the page to update
|
157
|
+
# page_name - the name of the page
|
158
|
+
# feature_content - the feature content to compare/update
|
159
|
+
#
|
160
|
+
# Returns the page
|
161
|
+
def update_wiki_page(wiki_page, page_name, feature_content)
|
162
|
+
wiki_page_content = wiki_page.raw_data
|
163
|
+
new_page_content = build_page_content(feature_content, wiki_page_content)
|
164
|
+
|
165
|
+
if new_page_content == wiki_page_content
|
166
|
+
puts " # Page #{page_name} didn't change"
|
167
|
+
else
|
168
|
+
@wiki.update_page(wiki_page, page_name, :markdown, new_page_content, @commit_info)
|
169
|
+
puts " # Updated Page: #{page_name}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
2
|
|
3
|
-
describe Gitnesse do
|
3
|
+
describe Gitnesse::Wiki do
|
4
|
+
let(:dir) { Dir.mktmpdir }
|
5
|
+
let(:wiki) { Gitnesse::Wiki.new(dir) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Dir.chdir(dir) do
|
9
|
+
`git init`
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
4
13
|
describe ".build_page_content" do
|
5
14
|
let(:wiki_page_content) do
|
6
15
|
<<-EOS
|
@@ -35,7 +44,7 @@ Feature: Addition
|
|
35
44
|
end
|
36
45
|
|
37
46
|
describe "without existing wiki page content" do
|
38
|
-
let(:method) { lambda {
|
47
|
+
let(:method) { lambda { wiki.build_page_content(new_feature_content) } }
|
39
48
|
let(:expected_result) do
|
40
49
|
"```gherkin
|
41
50
|
Feature: Addition
|
@@ -55,7 +64,7 @@ Feature: Addition
|
|
55
64
|
end
|
56
65
|
|
57
66
|
describe "with existing wiki page content" do
|
58
|
-
let(:method) { lambda {
|
67
|
+
let(:method) { lambda { wiki.build_page_content(new_feature_content, wiki_page_content) } }
|
59
68
|
let(:expected_result) do
|
60
69
|
<<-EOS
|
61
70
|
# Addition is Awesome
|