gitnesse 0.1.3 → 0.12.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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