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.
@@ -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
@@ -3,10 +3,10 @@ require 'rails'
3
3
 
4
4
  module Gitnesse
5
5
  class Railtie < Rails::Railtie
6
- railtie_name :gitnesse
6
+ railtie_name :gitnesse
7
7
 
8
8
  rake_tasks do
9
9
  load File.dirname(__FILE__) + '/tasks.rake'
10
10
  end
11
11
  end
12
- end
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'gitnesse'
2
+
3
+ Gitnesse::Hooks.setup
4
+
5
+ After do |scenario|
6
+ Gitnesse::Hooks.append_to_wiki(scenario)
7
+ end
8
+
9
+ at_exit do
10
+ Gitnesse::Hooks.teardown
11
+ end
@@ -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.load_config
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.load_config
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.load_config
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.load_config
26
- puts Gitnesse.config_to_hash.to_yaml
31
+ Gitnesse::Configuration.load_using_search
32
+ puts Gitnesse.configuration.to_yaml
27
33
  end
28
- end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Gitnesse
2
- VERSION = "0.1.3"
2
+ VERSION = "0.12.5"
3
3
  end
@@ -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 { Gitnesse.build_page_content(new_feature_content) } }
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 { Gitnesse.build_page_content(new_feature_content, wiki_page_content) } }
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