greenpepper-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/bin/greenpepperize +71 -0
  2. data/bin/greenpepperrails +33 -0
  3. data/bin/greenpepperruby +15 -0
  4. data/data/greenpepper.rake +37 -0
  5. data/data/helper.rb +32 -0
  6. data/data/tags +6 -0
  7. data/lib/greenpepper/argumentparser.rb +161 -0
  8. data/lib/greenpepper/common/loadpath.rb +7 -0
  9. data/lib/greenpepper/context/htmlcontext.rb +26 -0
  10. data/lib/greenpepper/converter.rb +347 -0
  11. data/lib/greenpepper/core.rb +152 -0
  12. data/lib/greenpepper/example/collectionexample.rb +305 -0
  13. data/lib/greenpepper/example/dowithexample.rb +192 -0
  14. data/lib/greenpepper/example/exampleheader.rb +41 -0
  15. data/lib/greenpepper/example/examplewithfixture.rb +73 -0
  16. data/lib/greenpepper/example/executionresults.rb +160 -0
  17. data/lib/greenpepper/example/fieldaccessor.rb +36 -0
  18. data/lib/greenpepper/example/freetextexample.rb +51 -0
  19. data/lib/greenpepper/example/importexample.rb +39 -0
  20. data/lib/greenpepper/example/nameresolver.rb +69 -0
  21. data/lib/greenpepper/example/ruleforexample.rb +117 -0
  22. data/lib/greenpepper/example/setupexample.rb +79 -0
  23. data/lib/greenpepper/example/silentexample.rb +14 -0
  24. data/lib/greenpepper/example/unknownexample.rb +17 -0
  25. data/lib/greenpepper/exception/greenpepperexception.rb +57 -0
  26. data/lib/greenpepper/executionunit.rb +39 -0
  27. data/lib/greenpepper/factory/collectionexamplefactory.rb +59 -0
  28. data/lib/greenpepper/factory/dowithexamplefactory.rb +71 -0
  29. data/lib/greenpepper/factory/examplefactory.rb +14 -0
  30. data/lib/greenpepper/factory/freetextexamplefactory.rb +29 -0
  31. data/lib/greenpepper/factory/htmlexamplefactory.rb +49 -0
  32. data/lib/greenpepper/factory/importexamplefactory.rb +27 -0
  33. data/lib/greenpepper/factory/ruleforexamplefactory.rb +46 -0
  34. data/lib/greenpepper/factory/setupexamplefactory.rb +31 -0
  35. data/lib/greenpepper/factory/silentexamplefactory.rb +21 -0
  36. data/lib/greenpepper/factory/unknownexamplefactory.rb +16 -0
  37. data/lib/greenpepper/freetext.rb +164 -0
  38. data/lib/greenpepper/grammar/array.treetop +51 -0
  39. data/lib/greenpepper/grammar/arrayparser.rb +14 -0
  40. data/lib/greenpepper/greenpepperconfig.rb +19 -0
  41. data/lib/greenpepper/greenpeppertask.rb +60 -0
  42. data/lib/greenpepper/logger.rb +45 -0
  43. data/lib/greenpepper/parser/freetextparser.rb +96 -0
  44. data/lib/greenpepper/parser/htmlparser.rb +70 -0
  45. data/lib/greenpepper/parser/scenario.rb +25 -0
  46. data/lib/greenpepper/parser/table.rb +37 -0
  47. data/lib/greenpepper/parser/wikiparser.rb +26 -0
  48. data/lib/greenpepper/pass/freetextpass.rb +24 -0
  49. data/lib/greenpepper/pass/greenpepperpass.rb +92 -0
  50. data/lib/greenpepper/pass/tablepass.rb +38 -0
  51. data/lib/greenpepper/railsargumentparser.rb +46 -0
  52. data/lib/greenpepper/redpeppertask.rb +89 -0
  53. data/lib/greenpepper/repository/atlassianrepository.rb +100 -0
  54. data/lib/greenpepper/writer/consolewriter.rb +21 -0
  55. data/lib/greenpepper/writer/freetextresult.rb +233 -0
  56. data/lib/greenpepper/writer/freetextwriter.rb +44 -0
  57. data/lib/greenpepper/writer/html.rb +14 -0
  58. data/lib/greenpepper/writer/htmldocwriter.rb +82 -0
  59. data/lib/greenpepper/writer/htmlresult.rb +192 -0
  60. data/lib/greenpepper/writer/htmlwriter.rb +112 -0
  61. data/lib/greenpepper/writer/output.rb +26 -0
  62. data/lib/greenpepper/writer/result.rb +35 -0
  63. data/lib/greenpepper/writer/xmlwriter.rb +32 -0
  64. data/test/coreseedstest.rb +39 -0
  65. data/test/greenpepper/argumentparsertest.rb +162 -0
  66. data/test/greenpepper/common/loadpathtest.rb +24 -0
  67. data/test/greenpepper/common/stattest.rb +186 -0
  68. data/test/greenpepper/convertertest.rb +371 -0
  69. data/test/greenpepper/coretest.rb +159 -0
  70. data/test/greenpepper/example/collectionexampletest.rb +484 -0
  71. data/test/greenpepper/example/dowithexampletest.rb +148 -0
  72. data/test/greenpepper/example/exampletest.rb +28 -0
  73. data/test/greenpepper/example/freetextexampletest.rb +151 -0
  74. data/test/greenpepper/example/importexampletest.rb +79 -0
  75. data/test/greenpepper/example/nameresolvertest.rb +56 -0
  76. data/test/greenpepper/example/ruleforexampletest.rb +225 -0
  77. data/test/greenpepper/example/setupexampletest.rb +140 -0
  78. data/test/greenpepper/example/silentexampletest.rb +17 -0
  79. data/test/greenpepper/example/unknownexampletest.rb +17 -0
  80. data/test/greenpepper/factory/collectionexamplefactorytest.rb +51 -0
  81. data/test/greenpepper/factory/dowithexamplefactorytest.rb +48 -0
  82. data/test/greenpepper/factory/examplefactorytest.rb +88 -0
  83. data/test/greenpepper/factory/freetextexamplefactorytest.rb +54 -0
  84. data/test/greenpepper/factory/importexamplefactorytest.rb +40 -0
  85. data/test/greenpepper/factory/ruleforexamplefactorytest.rb +55 -0
  86. data/test/greenpepper/factory/setupexamplefactorytest.rb +29 -0
  87. data/test/greenpepper/factory/silentexamplefactorytest.rb +38 -0
  88. data/test/greenpepper/freetexttest.rb +222 -0
  89. data/test/greenpepper/grammar/arrayparsertest.rb +45 -0
  90. data/test/greenpepper/loggertest.rb +26 -0
  91. data/test/greenpepper/parser/freetextparsertest.rb +124 -0
  92. data/test/greenpepper/parser/htmlparsertest.rb +77 -0
  93. data/test/greenpepper/parser/wikiparsertest.rb +21 -0
  94. data/test/greenpepper/pass/freetextpasstest.rb +54 -0
  95. data/test/greenpepper/pass/greenpepperpasstest.rb +47 -0
  96. data/test/greenpepper/pass/tablepasstest.rb +23 -0
  97. data/test/greenpepper/repository/atlassionrepositorytest.rb +85 -0
  98. data/test/greenpepper/writer/freetextwritertest.rb +301 -0
  99. data/test/greenpepper/writer/htmlcollectionwritertest.rb +145 -0
  100. data/test/greenpepper/writer/htmldowithwritertest.rb +87 -0
  101. data/test/greenpepper/writer/htmlruleforwritertest.rb +147 -0
  102. data/test/greenpepper/writer/htmlsetupwritertest.rb +107 -0
  103. data/test/greenpepper/writer/htmlstatresulttest.rb +118 -0
  104. data/test/greenpepper/writer/htmlwriterpositiontest.rb +53 -0
  105. data/test/greenpepper/writer/writertest.rb +33 -0
  106. data/test/greenpepper/writer/xmlwritertest.rb +34 -0
  107. data/test/integration/collectionexampleintegrationtest.rb +64 -0
  108. data/test/integration/errorhandlingintegrationtest.rb +68 -0
  109. data/test/integration/freetextexampleintegrationtest.rb +75 -0
  110. data/test/integration/greenpepperexecutableintegrationtest.rb +22 -0
  111. data/test/integration/importexampleintegrationtest.rb +41 -0
  112. data/test/integration/interpretationordertest.rb +48 -0
  113. data/test/integration/ruleforexampleintegrationtest.rb +102 -0
  114. data/test/integration/securityintegrationtest.rb +30 -0
  115. data/test/integration/setupexampleintegrationtest.rb +31 -0
  116. data/test/integration/silentexampleintegrationtest.rb +29 -0
  117. data/test/task/greenpeppertasktest.rb +96 -0
  118. data/test/task/redpeppertasktest.rb +120 -0
  119. data/vendor/accents.rb +85 -0
  120. metadata +234 -0
@@ -0,0 +1,24 @@
1
+ =begin
2
+ Author: Simon Mathieu (simon.math@gmail.com)
3
+ Pascal Ouellet (pas.ouellet@gmail.com)
4
+ Date: October 5, 2009
5
+ =end
6
+
7
+ module GreenPepper
8
+
9
+ require 'greenpepper/factory/freetextexamplefactory'
10
+ require 'greenpepper/parser/freetextparser'
11
+ require 'greenpepper/writer/freetextwriter'
12
+
13
+ require 'greenpepper/pass/greenpepperpass'
14
+
15
+ class FreeTextPass < GreenPepperPass
16
+ def initialize()
17
+ parser = FreeTextParser.new
18
+ factory = FreeTextExampleFactory.new
19
+ writer = FreeTextWriter.new
20
+ super(parser, factory, writer)
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,92 @@
1
+ =begin
2
+ Author: Pascal Ouellet (pas.ouellet@gmail.com)
3
+ Date: October 27, 2009
4
+ =end
5
+
6
+
7
+
8
+ module GreenPepper
9
+ class GreenPepperPass
10
+
11
+ @@passes = []
12
+ attr_accessor :writer
13
+ # TODO Malformed do with table test
14
+ def initialize(parser, factory, writer)
15
+ @parser = parser
16
+ @factory = factory
17
+ @writer = writer
18
+ # Force LibXML to keep the line number when parsing
19
+ LibXML::XML::default_line_numbers = true
20
+ end
21
+
22
+ def extract_data document, filename
23
+ # Extract the content of the document
24
+ execution_units = @parser.extract_content document, filename
25
+
26
+ # Build examples from the content
27
+ i = 0
28
+ new_execution_units = []
29
+ while i < execution_units.size
30
+ content = execution_units[i].content
31
+ context = execution_units[i].context
32
+
33
+ current_unit = i
34
+ @factory.push_content content
35
+ i += 1
36
+ while @factory.need_more_content?
37
+
38
+ if i >= execution_units.size
39
+ raise GreenPepperMalformedTableError.new(
40
+ "Can't parse document, one of the table is not formated correctly.")
41
+ end
42
+
43
+ content = @factory.push_content execution_units[i].content
44
+ context.nb_table +=1
45
+ i += 1
46
+ end
47
+ example = @factory.build_example
48
+ execution_units[current_unit].example = example
49
+ new_execution_units << execution_units[current_unit]
50
+ end
51
+ new_execution_units
52
+ end
53
+
54
+ def write document, execution_units, writer_options
55
+ if execution_units.size > 0
56
+ document = @writer.write document, execution_units, writer_options
57
+ end
58
+ document
59
+ end
60
+
61
+ def self.interpret(document, filename = 'UNKNOWN', writer_options = {})
62
+ ex_units = []
63
+ @@passes.each{|pass| ex_units += pass.extract_data(document, filename)}
64
+
65
+ ex_units.sort!{|first, second|first.context.index <=> second.context.index}
66
+ # Execute examples
67
+ ex_units.each{ |ex_unit|
68
+ ex_unit.execute
69
+ }
70
+
71
+ # Don't write unless we have to
72
+ pass_it = 0
73
+ @@passes.each{|pass|
74
+ temp_units = []
75
+ ex_units.each{|unit|
76
+ if pass.writer.support? unit
77
+ temp_units << unit
78
+ end
79
+ }
80
+
81
+ document = pass.write(document, temp_units, writer_options)
82
+ }
83
+ [ex_units, document]
84
+ end
85
+
86
+ def self.passes=(passes)
87
+ @@passes = passes
88
+ end
89
+ end
90
+
91
+ end
92
+
@@ -0,0 +1,38 @@
1
+ =begin
2
+ Author: Simon Mathieu (simon.math@gmail.com)
3
+ Pascal Ouellet (pas.ouellet@gmail.com)
4
+ Date: October 5, 2009
5
+ =end
6
+ module GreenPepper
7
+
8
+ require 'greenpepper/parser/htmlparser'
9
+ require 'greenpepper/factory/examplefactory'
10
+ require 'greenpepper/writer/htmlwriter'
11
+ require 'greenpepper/factory/htmlexamplefactory'
12
+ require 'greenpepper/factory/ruleforexamplefactory'
13
+ require 'greenpepper/factory/importexamplefactory'
14
+ require 'greenpepper/factory/setupexamplefactory'
15
+ require 'greenpepper/factory/dowithexamplefactory'
16
+ require 'greenpepper/factory/collectionexamplefactory'
17
+ require 'greenpepper/factory/silentexamplefactory'
18
+
19
+ require 'greenpepper/pass/greenpepperpass'
20
+
21
+ class TablePass < GreenPepperPass
22
+ def initialize()
23
+ parser = HtmlParser.new
24
+ factory = HtmlExampleFactory.new([ImportExampleFactory.new,
25
+ RuleForExampleFactory.new,
26
+ SetupExampleFactory.new,
27
+ DoWithExampleFactory.new,
28
+ ListOfExampleFactory.new,
29
+ SetOfExampleFactory.new,
30
+ SubsetOfExampleFactory.new,
31
+ SupersetOfExampleFactory.new,
32
+ SilentExampleFactory.new
33
+ ])
34
+ writer = HtmlWriter.new
35
+ super(parser, factory, writer)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,46 @@
1
+ =begin
2
+ author : S�bastien Boisclair (sebastien.boisclair2@usherbrooke.ca)
3
+ date: November 26, 2009
4
+ =end
5
+ module RailsArgumentParser
6
+
7
+ def self.extract_args
8
+ args = {}
9
+
10
+ env = extract_single_arg("--env")
11
+ args[:env] = env
12
+
13
+ path = extract_single_arg("--rails")
14
+ args[:rails] = path
15
+ args
16
+ end
17
+
18
+ def self.extract_single_arg(argument)
19
+ ind = ARGV.index(argument)
20
+ result = nil
21
+ if ind != nil
22
+ if ind + 1 >= ARGV.length
23
+ puts "Wrong number of arguments.\n"
24
+ puts argument + " needs a linked argument."
25
+ ARGV.delete_at(ind)
26
+ else
27
+ result = ARGV[ind+1]
28
+ ARGV.delete_at(ind+1)
29
+ ARGV.delete_at(ind)
30
+ end
31
+ end
32
+ result
33
+ end
34
+
35
+ def self.usage
36
+ index = ARGV.index('--help')
37
+ if ARGV.length == 0 || index != nil
38
+ puts "Usage: ruby greenpepperrails input_document output_document [option]"
39
+ puts "--rails path to the rails application"
40
+ puts "--env name of the environment of rails application"
41
+ puts "all the options that can be used with greenpepper.rb can be used " +
42
+ "with greenpepperrails\n\n"
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'libxml'
5
+ require 'rake'
6
+ require 'rake/tasklib'
7
+ require 'net/http'
8
+ require 'cgi'
9
+ require 'greenpepper/greenpepperconfig'
10
+
11
+ module GreenPepper
12
+ class RedPepperTask < Rake::TaskLib
13
+ attr_accessor :server, :path, :spec_id, :spec_name
14
+
15
+ def initialize(name, http = Net::HTTP)
16
+ @name = name
17
+ @http_client = http
18
+ @path = 'greenpepper/specifications'
19
+
20
+ yield self if block_given?
21
+ load_config
22
+ define
23
+ end
24
+
25
+ private
26
+ # Create the tasks defined by this task lib.
27
+ def define
28
+ task @name do
29
+ if @spec_id.nil? && @spec_name.nil?
30
+ download_all_specs
31
+ else
32
+ if @spec_name
33
+ url = get_url_for_name @spec_name
34
+ name = @spec_name
35
+ elsif @spec_id
36
+ url = get_url_for_id @spec_id
37
+ name = @spec_id.to_s
38
+ end
39
+ page = get_page(url)
40
+ name = parse_for_name(page)
41
+
42
+ write_page page, name
43
+ end
44
+ end
45
+ end
46
+
47
+ def download_all_specs
48
+ all_ids_string = @http_client.get URI.parse("#{@server}/specifications/all")
49
+ all_ids_string.split("\n").each do |id|
50
+ url = get_url_for_id(id)
51
+ page = get_page(url)
52
+ name = parse_for_name page
53
+ write_page page, name
54
+ end
55
+ end
56
+
57
+ def get_url_for_id id
58
+ "#{@server}/specifications/spec/#{id}"
59
+ end
60
+
61
+ def get_url_for_name name
62
+ "#{@server}/specifications/spec/name/#{CGI::escape name}"
63
+ end
64
+
65
+ def get_page url
66
+ @http_client.get URI.parse(url)
67
+ end
68
+
69
+ def write_page(page, name)
70
+ filepath = File.join @path, name + '.html'
71
+ FileUtils.mkdir_p @path if !File.directory?(@path)
72
+ File.open(filepath, 'w') { |f| f.write page }
73
+ end
74
+
75
+ def parse_for_name page
76
+ page_parse = (LibXML::XML::HTMLParser.string page).parse
77
+ name = ""
78
+ page_parse.find("//title").each {|t| name = t.content}
79
+ name.strip
80
+ end
81
+
82
+
83
+ def load_config
84
+ config = GreenPepperConfig.instance
85
+ GreenPepperConfig.maybe_set self, "@server", config
86
+ GreenPepperConfig.maybe_set self, "@path", config
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,100 @@
1
+ =begin
2
+ author: Éloise Dubé (eloise.dube@gmail.com)
3
+ date: March 29, 2009
4
+ =end
5
+ module GreenPepper
6
+
7
+ require 'cgi'
8
+ require 'xmlrpc/client'
9
+ require 'greenpepper/exception/greenpepperexception'
10
+
11
+ class AtlassianRepository
12
+
13
+ def initialize(uri, server = nil)
14
+ uri = AtlassianURI.new(uri) if uri.is_a?(String)
15
+ @uri = uri
16
+ server = Confluence::Server.new(@uri.url, @uri.handler) unless server
17
+ @repo = server
18
+ end
19
+
20
+ def load_document(filename)
21
+ filename = CGI::unescape(filename)
22
+
23
+ parse_input_filename filename
24
+ return @repo.getRenderedSpecification(@uri.username, @uri.password,
25
+ [@uri.space, @input_filename, false, true])
26
+ end
27
+
28
+ def parse_input_filename(filename)
29
+ # format of filename : FILENAME?ATTRIBUTES
30
+ @file_attributes = Hash.new
31
+
32
+ filename_parts = filename.split "?"
33
+ @input_filename = filename_parts[0]
34
+ if filename_parts.size > 1
35
+ attribute_parts = filename_parts[1].split "="
36
+ @file_attributes[attribute_parts[0]] = attribute_parts[1]
37
+ end
38
+ end
39
+ end
40
+
41
+ class AtlassianURI
42
+ attr_reader :uri, :url, :handler, :space, :username, :password
43
+ def initialize(uri)
44
+ @uri = uri
45
+ uri_parts = @uri.split ";"
46
+ if uri_parts.size < 2
47
+ raise GreenPepperRepositoryError.new("Bad format of URI. " + uri)
48
+ end
49
+
50
+ success = /(.*)\?handler=(.*)&(.*)#(.*)/ === uri_parts[1]
51
+ if success == false
52
+ raise GreenPepperRepositoryError.new(
53
+ "Can't parse confluence URL")
54
+ end
55
+ @url = $1
56
+ @handler = $2
57
+ @space = $4
58
+ attribute_parts = $3.split "="
59
+
60
+ @username = ""
61
+ @password = ""
62
+
63
+ if uri_parts.size > 2
64
+ @username = uri_parts[2]
65
+ @password = uri_parts[3]
66
+ end
67
+ end
68
+ end
69
+
70
+ # A useful helper for running Confluence XML-RPC from Ruby.
71
+ # Also takes care of re-logging in if your login times out.
72
+ #
73
+ # Source code :
74
+ # http://confluence.atlassian.com/display/CONFEXT/Confluence4r
75
+ module Confluence
76
+ class ServerFactory
77
+ def create_server(server_url)
78
+ XMLRPC::Client.new2 server_url
79
+ end
80
+ end
81
+ class Server
82
+ def initialize(server_url, handler, factory = ServerFactory.new)
83
+ unless server_url[-11..-1] == "/rpc/xmlrpc"
84
+ server_url += "/rpc/xmlrpc"
85
+ end
86
+ server = factory.create_server server_url
87
+ @conf = server.proxy handler
88
+ end
89
+
90
+ def method_missing(method_name, *args)
91
+ begin
92
+ @conf.send(method_name, *(args))
93
+ rescue XMLRPC::FaultException => e
94
+ raise e.faultString
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ end #module GreenPepper
@@ -0,0 +1,21 @@
1
+ =begin
2
+ author: Martin Provencher (martin.provencher@usherbrooke.ca)
3
+ date: March 18, 2009
4
+ =end
5
+ module GreenPepper
6
+
7
+ require 'greenpepper/example/ruleforexample'
8
+
9
+ class ConsoleWriter
10
+ def initialize results
11
+ @results = results
12
+ end
13
+
14
+ def output
15
+ results = HtmlTableExecutionResults.get_all_results(@results)
16
+ total = results.successes + results.failures + results.ignored + results.errors
17
+ "#{total} tests: #{results.successes} right, #{results.failures}" +
18
+ " wrong, #{results.ignored} ignored, #{results.errors} exception(s)"
19
+ end
20
+ end
21
+ end #module GreenPepper
@@ -0,0 +1,233 @@
1
+ =begin
2
+ author: Simon Mathieu (simon.math@gmail.com)
3
+ date: October 3, 2009
4
+ =end
5
+ module GreenPepper
6
+
7
+ require 'greenpepper/writer/html'
8
+ require 'greenpepper/writer/result'
9
+ require 'greenpepper/converter'
10
+ require 'cgi'
11
+
12
+ module KeywordFormat
13
+ def indent(text)
14
+ "<div class=\"greenpepper-freetext-indent\">#{text}</div>"
15
+ end
16
+
17
+ def indent2(text)
18
+ "<div class=\"greenpepper-freetext-indent2\">#{text}</div>"
19
+ end
20
+
21
+ def newline(text)
22
+ "<div class=\"greenpepper-freetext\">#{text}</div>"
23
+ end
24
+
25
+ def highlight(color, text)
26
+ "<font style=\"background-color: #{color};\">#{text}</font>"
27
+ end
28
+
29
+ def yellow_highlight(text)
30
+ highlight(Html::YELLOW, text)
31
+ end
32
+
33
+ def green_highlight(text)
34
+ highlight(Html::GREEN, text)
35
+ end
36
+
37
+ def red_highlight(text)
38
+ highlight(Html::RED, text)
39
+ end
40
+
41
+ def grey_highlight(text)
42
+ highlight(Html::GREY, text)
43
+ end
44
+
45
+ def error(error)
46
+ res = indent yellow_highlight("#{error.class}: " +
47
+ "#{CGI::escapeHTML error.to_s}")
48
+ if error.backtrace
49
+ res += '<hr/>'
50
+ error.backtrace.each { |step|
51
+ res << indent2(yellow_highlight(CGI::escapeHTML(step)))
52
+ }
53
+ end
54
+ res
55
+ end
56
+ end
57
+
58
+ class GivenSuccess < ExampleResult
59
+ def write(action)
60
+ action
61
+ end
62
+
63
+ def success?
64
+ true
65
+ end
66
+ end
67
+
68
+ class WhenSuccess < ExampleResult
69
+ def write(action)
70
+ action
71
+ end
72
+
73
+ def success?
74
+ true
75
+ end
76
+ end
77
+
78
+ class ThenResults < ExampleResult
79
+ include KeywordFormat
80
+ attr_accessor :expectations
81
+
82
+ def initialize(regex, expectations)
83
+ @regex, @expectations = regex, expectations
84
+ end
85
+
86
+ def write(action)
87
+ expected_lines = []
88
+ match_data = @regex.match action
89
+ i = match_data.size - 1
90
+ while i > 0
91
+ start_index = match_data.offset(i)[0]
92
+ end_index = match_data.offset(i)[1]
93
+
94
+ # Type conversion of expected and received value
95
+ converter = TypeConverter.instance
96
+ expected = converter.format_object(match_data[i],
97
+ @expectations[i-1].expected)
98
+ received = converter.format_object(match_data[i],
99
+ @expectations[i-1].received)
100
+
101
+ # Highlight match
102
+ action = action[0...start_index] +
103
+ then_highlight(expected,
104
+ @expectations[i-1].check_result) +
105
+ action[end_index..-1]
106
+
107
+ # Write expected lines for failures
108
+ unless @expectations[i-1].check_result
109
+ expected_lines << indent(
110
+ red_highlight("Expected value was #{expected}, " +
111
+ "but #{received} was received"))
112
+ end
113
+ i -= 1
114
+ end
115
+
116
+ expected_lines.reverse.each do |line|
117
+ action += line
118
+ end
119
+
120
+ action
121
+ end
122
+
123
+ def then_highlight(string, result)
124
+ result ? green_highlight(string) : red_highlight(string)
125
+ end
126
+
127
+ def update_stats(results)
128
+ @expectations[0..-1].each do |exp|
129
+ exp.check_result ? results.add_success : results.add_failure
130
+ end
131
+ end
132
+ end
133
+
134
+ class AskSuccess < ExampleResult
135
+ include KeywordFormat
136
+ attr_accessor :answer
137
+
138
+ def initialize(answer)
139
+ @answer = answer
140
+ end
141
+
142
+ def write(action)
143
+ action + indent("Answer: " + grey_highlight(@answer))
144
+ end
145
+
146
+ def success?
147
+ true
148
+ end
149
+ end
150
+
151
+ class CheckSuccess < ExampleResult
152
+ include KeywordFormat
153
+
154
+ def write(action)
155
+ green_highlight action
156
+ end
157
+
158
+ def update_stats(results)
159
+ results.add_success
160
+ end
161
+
162
+ def success?
163
+ true
164
+ end
165
+ end
166
+
167
+ class HeaderSuccess < ExampleResult
168
+ def initialize(fixture_name)
169
+ @fixture_name = fixture_name
170
+ end
171
+
172
+ def write(action)
173
+ "Scenario: #{@fixture_name}"
174
+ end
175
+
176
+ def success?
177
+ true
178
+ end
179
+ end
180
+
181
+ class KeywordError < ExampleResult
182
+ include KeywordFormat
183
+ def update_stats(results)
184
+ results.add_error
185
+ end
186
+
187
+ def error?
188
+ true
189
+ end
190
+ end
191
+
192
+ class ActionError < KeywordError
193
+ attr_reader :exception
194
+
195
+ def initialize(exception)
196
+ @exception = exception
197
+ end
198
+
199
+ def write(action)
200
+ newline(yellow_highlight(action)) +
201
+ error(@exception)
202
+ end
203
+ end
204
+
205
+ class HeaderError < KeywordError
206
+ def initialize(fixture_name, error)
207
+ @fixture_name = fixture_name
208
+ @error = error
209
+ end
210
+
211
+ def write(action)
212
+ "Scenario: " + yellow_highlight(@fixture_name) +
213
+ indent(error(@error))
214
+ end
215
+ end
216
+
217
+ class CheckFailure < ExampleResult
218
+ include KeywordFormat
219
+
220
+ def write(action)
221
+ red_highlight action
222
+ end
223
+
224
+ def update_stats(results)
225
+ results.add_failure
226
+ end
227
+
228
+ def failure?
229
+ true
230
+ end
231
+ end
232
+
233
+ end