greenpepper-ruby 0.0.1

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.
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,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Greenpepperize the folder by deploying rake tasks
4
+ require 'fileutils'
5
+
6
+ module GreenPepper
7
+ module Deploy
8
+ FOLDERS = ["greenpepper/specifications", "greenpepper/results",
9
+ "greenpepper/fixtures", "lib/tasks"]
10
+
11
+ def self.deploy
12
+ no_argument_error if ARGV.size != 1
13
+ deploy_path = File.expand_path ARGV[0]
14
+ inexistant_path_error if !File.exists? deploy_path
15
+ return if !confirm? deploy_path
16
+
17
+ gem_data_dir = File.join(File.dirname(__FILE__), '..', 'data')
18
+
19
+ # Create folders
20
+ FOLDERS.each{ |folder| FileUtils.mkdir_p File.join(deploy_path, folder)}
21
+
22
+ # Deploy files
23
+ FileUtils.cp File.join(gem_data_dir, 'greenpepper.rake'),
24
+ File.join(deploy_path, 'lib/tasks')
25
+ FileUtils.cp File.join(gem_data_dir, 'helper.rb'),
26
+ File.join(deploy_path, 'greenpepper')
27
+
28
+ print_info
29
+ end
30
+
31
+ private
32
+ def self.confirm? path
33
+ puts "Do you want to deploy GreenPepper to \"#{path}\"? [y/n]"
34
+ begin
35
+ answer = STDIN.gets.chomp
36
+ end while answer != "y" && answer != "n"
37
+ answer == "y" ? true : false
38
+ end
39
+
40
+ def self.no_argument_error
41
+ puts "Invalid argument specified."
42
+ print_usage
43
+ exit 1
44
+ end
45
+
46
+ def self.inexistant_path_error
47
+ puts "Inexistant path specified."
48
+ print_usage
49
+ exit 1
50
+ end
51
+
52
+ def self.print_usage
53
+ puts "usage: greenpepperize PATH"
54
+ end
55
+
56
+ def self.print_info
57
+ puts "The directory has been greenpeperized.\n\n" +
58
+ "The following rake tasks are now available: \n" +
59
+ " gp:all [name=\"spec\"] - Download and run one or all" +
60
+ " specifications\n" +
61
+ " gp:download [name=\"spec\"] - Download one or all specifications" +
62
+ " from RedPepper server\n" +
63
+ " gp:run [name=\"spec\"] - Execute one or all specifications" +
64
+ " from greenpepper/specification\n\n" +
65
+ "The greenpepper/helper.rb file can be used to configure the tasks.\n"
66
+ end
67
+ end
68
+ end
69
+
70
+ GreenPepper::Deploy.deploy
71
+ exit 0
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ =begin
3
+ author : S�bastien Boisclair (sebastien.boisclair2@usherbrooke.ca)
4
+ date: November 26, 2009
5
+ =end
6
+
7
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
8
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "../bin")
9
+
10
+ require 'rubygems'
11
+ require 'greenpepper/railsargumentparser'
12
+ require 'greenpepper/freetext'
13
+ args = RailsArgumentParser.extract_args
14
+
15
+ if !args[:env]
16
+ RAILS_ENV = "test"
17
+ else
18
+ RAILS_ENV = args[:env]
19
+ end
20
+
21
+ if args[:rails]
22
+ require File.join(args[:rails], 'config/environment.rb')
23
+ requires = Dir.glob File.join(args[:rails], "greenpepper", "fixtures",
24
+ "*.rb")
25
+ requires.each { |req| require req }
26
+ end
27
+
28
+ index = ARGV.index('--help')
29
+ if ARGV.length == 0 || index != nil
30
+ RailsArgumentParser.usage
31
+ end
32
+
33
+ load 'greenpepperruby'
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ =begin
3
+ author : Martin Provencher (martin.provencher@usherbrooke.ca)
4
+ date: March 11, 2009
5
+ =end
6
+
7
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
8
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "../../common")
9
+
10
+ require 'greenpepper/core.rb'
11
+
12
+ core = GreenPepper::GreenPepperCore.new
13
+ ret = core.run ARGV
14
+
15
+ exit(ret) if ret.is_a? Fixnum
@@ -0,0 +1,37 @@
1
+ # Tasks to download and execute GreenPepper specifications against the Rails
2
+ # application. Tasks configuration file is located in greenpepper/helper.rb
3
+ require 'greenpepper/greenpeppertask'
4
+ require 'greenpepper/redpeppertask'
5
+
6
+ # Load the configuration file
7
+ load 'greenpepper/helper.rb'
8
+
9
+ # Global GreenPepper namespace
10
+ namespace :gp do
11
+
12
+ # Download and run all specifications
13
+ task :all do
14
+ Rake::Task["gp:download"].execute
15
+ Rake::Task["gp:run"].execute
16
+ end
17
+
18
+ # Download all the specifications hosted by the RedPepper server defined
19
+ # in the config file
20
+ GreenPepper::RedPepperTask.new(:download) do |t|
21
+ # Get the spec name, if any
22
+ t.spec_name = ENV['name']
23
+ end
24
+
25
+ # Execute all specifications in greenpepper/specifications
26
+ GreenPepper::GreenPepperTask.new(:run) do |t|
27
+ # Require Rails environment
28
+ require "config/environment"
29
+
30
+ # Require fixtures in greenpepper/fixtures
31
+ requires = Dir.glob File.join("greenpepper", "fixtures", "*.rb")
32
+ requires.each { |req| require req }
33
+
34
+ # Get the spec name, if any
35
+ t.spec_name = ENV['name'] + '.html'
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # GreenPepper rake tasks configuration file. Change this file to customize
2
+ # the behavior of the gp:all, gp:download and gp:run tasks.
3
+ require 'greenpepper/greenpepperconfig'
4
+
5
+ # Include the freetext DSL.
6
+ require 'greenpepper/freetext'
7
+
8
+ GreenPepper::GreenPepperConfig.configure do |config|
9
+
10
+ ### RedPepper ###
11
+ #################
12
+ # Defines the RedPepper server URL from which to fetch the specifications
13
+ config.server = "http://greenpepper.kicks-ass.org/server"
14
+
15
+ # The directory to save the downloaded specifications to.
16
+ # Default : "greenpepper/specifications"
17
+ #config.path = "path/specifications"
18
+
19
+ ### Specification ###
20
+ #####################
21
+ # The directory from which to execute the specifications
22
+ # Default : "greenpepper/specifications"
23
+ #config.spec_dir = "/my/spec/dir"
24
+
25
+ # The execution result directory.
26
+ # Defaut : "greenpepper/results"
27
+ #config.result_dir = "path/results"
28
+
29
+ # The path of the GreenPepper core. If not specified, it searches for it in
30
+ # the ruby loadpath.
31
+ #config.greenpepper_path = "/my/core/path"
32
+ end
@@ -0,0 +1,6 @@
1
+ !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
2
+ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
3
+ !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
4
+ !_TAG_PROGRAM_NAME Exuberant Ctags //
5
+ !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
6
+ !_TAG_PROGRAM_VERSION 5.7 //
@@ -0,0 +1,161 @@
1
+ =begin
2
+ author: Martin Provencher (martin.provencher@usherbrooke.ca)
3
+ date: March 24, 2008
4
+ =end
5
+ module GreenPepper
6
+
7
+ class ArgumentParser
8
+
9
+ attr_reader :execution_context, :writer_context
10
+
11
+ def initialize(args)
12
+ @execution_context = {:html_results_output => true,
13
+ :xml_output => false,
14
+ :console_output => "",
15
+ :repository => nil,
16
+ :load_path => Array.new,
17
+ :input_document => nil,
18
+ :output_document => nil}
19
+
20
+ @writer_context = {:no_exception_stack => false}
21
+
22
+ if args.empty?
23
+ @execution_context[:console_output] = ArgumentParser.usage
24
+ else
25
+ @parsed = parse_args args
26
+ end
27
+ end
28
+
29
+ def parse_args(argv)
30
+ argv = [argv] unless argv.is_a? Array
31
+ args = argv.dup
32
+ arg_regex = /^\s*-.+\s*/
33
+ return false if args.size < 1
34
+
35
+ while arg = args.shift
36
+ if arg =~ arg_regex
37
+ case arg
38
+ when "--no-html-results" #Not in doc
39
+ @execution_context[:html_results_output] = false
40
+ when "--no-exception-stack"
41
+ @writer_context[:no_exception_stack] = true
42
+ when "--help"
43
+ @execution_context[:console_output] = ArgumentParser.usage
44
+ return
45
+ when "--version"
46
+ @execution_context[:console_output] =
47
+ "#{$APP_NAME} version : #{$VERSION}"
48
+ return
49
+ when "--xml"
50
+ @execution_context[:xml_output] = true
51
+ @execution_context[:output_document] = args.shift unless
52
+ args[0] =~ arg_regex || args.size == 0
53
+ #Output to the specified output. If no specified output,
54
+ #outputting to INPUTFILENAME_output.xml
55
+ when "-r"
56
+ if args[0] =~ arg_regex || args.size == 0
57
+ @execution_context[:console_output] = ArgumentParser.usage
58
+ return
59
+ else
60
+ @execution_context[:repository] = args.shift
61
+ end
62
+ when "--loadpath"
63
+ if args[0] =~ arg_regex || args.size == 0
64
+ @execution_context[:console_output] = ArgumentParser.usage
65
+ return
66
+ else
67
+ while !(args[0] =~ arg_regex || args.size == 0)
68
+ @execution_context[:load_path] << args.shift
69
+ end
70
+ end
71
+
72
+ else
73
+ @execution_context[:console_output] =
74
+ "#{arg.to_s} option is not recognize\n#{ArgumentParser.usage}"
75
+ return
76
+ end
77
+ else
78
+ if @execution_context[:input_document].nil?
79
+ @execution_context[:input_document] = arg
80
+ elsif @execution_context[:output_document].nil?
81
+ @execution_context[:output_document] = arg
82
+ end
83
+ end
84
+ end
85
+
86
+ if (@execution_context[:input_document].nil?)
87
+ @execution_context[:console_output] = ArgumentParser.usage
88
+ return
89
+ else
90
+ if(@execution_context[:output_document].nil?)
91
+ extension_name = File.extname @execution_context[:input_document]
92
+ base_name = File.basename @execution_context[:input_document]
93
+ base_name.gsub!(extension_name, "")
94
+ extension_name = '.xml' if @execution_context[:xml_output]
95
+
96
+ @execution_context[:output_document] =
97
+ "#{base_name}_output#{extension_name}"
98
+ end
99
+ end
100
+ end
101
+
102
+ def self.usage
103
+ str = "Usage: ruby greenpepper.rb input_document "
104
+ str += "[ouput_document] [options]\n\n"
105
+ str += "--help Display the help.\n"
106
+ str += "--version Output version information.\n"
107
+ str += "-r CLASS;ARGS The url of the repository of the" +
108
+ str += " specifications.\n"
109
+ str += "--no-html-results This option will not print result in output.\n"
110
+ str += "--xml [output_document] Generate XML report (default is plain text)."
111
+ str += " If output_document is specified, the xml report will outputed"
112
+ str += " in the specified file.\n"
113
+ str += "--no-exception-stack Disable outputting of exception stack when"
114
+ str += " execution exception are raised.\n"
115
+ str += "--load_path path1 [pathX] List of path to include for execution."
116
+ str
117
+ end
118
+
119
+ =begin
120
+ This doc came from greenpeppersoftware.com ... this will be needed to fill self.usage
121
+
122
+ Usage: greenpepper [options] input [ouput]
123
+ Run the input specification and produce a report in output file or in directory specified by -o
124
+
125
+ Options:
126
+ Ignore :-l, --locale LANG Set application language (en, fr, ...)
127
+ #-f, --sud CLASS;ARGS Use CLASS as the system under development and instantiate it with ARGS
128
+ #-o DIRECTORY Produce reports in DIRECTORY (defaults to current directory)
129
+ #-r CLASS;ARGS Use CLASS as the document repository and instantiate it with ARGS (defaults to com.greenpepper.repository.FileSystemRepository)
130
+ #-s, --suite Run a suite rather than a single test (output must refer to a directory)
131
+ -t SECTIONS Filter input specification to only execute SECTIONS (comma separated list of sections)
132
+ -a ARGS Semicolon seperated list of assemblies fullName
133
+
134
+ Ignore : --selector CLASS Use CLASS as the interpreter selector (defaults to com.greenpepper.document.GreenPepperInterpreterSelector)
135
+ # --lazy Set greenpepper in lazy mode for document execution
136
+ # --xml Generate XML report (defaults to plain)
137
+ # --help Display this help and exit
138
+ # --version Output version information and exit
139
+ Don't implement for now : --debug Enable debug mode
140
+ # --stop Stop the execution of the specification on the first failure
141
+
142
+ When no option is given, GreenPepper defaults to the following rules:
143
+
144
+ * Input is a single specification, not a suite
145
+ * If output is not specified, reports are produced in the current directory
146
+ * Report is in plain format
147
+ * The operating system locale is used
148
+ Not in story * The input specification is not filtered
149
+ * The specification file must be located on the file system
150
+ * Fixtures are created using the default built-in mechanism
151
+ * Tables use GreenPepper formalism
152
+ * Lazy mode is disabled
153
+ * Debug mode is disabled
154
+ * Will not stop the execution on first failure
155
+
156
+ Any of the rules above can be overridden using command line switches.
157
+
158
+ =end
159
+ end
160
+
161
+ end #module GreenPepper
@@ -0,0 +1,7 @@
1
+ module LoadPath
2
+ def self.load(paths)
3
+ paths.reverse.each{ |path|
4
+ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
5
+ }
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ =begin
2
+ author: Martin Provencher (mprovencher86@gmail.com)
3
+ date: September 3, 2009
4
+ =end
5
+
6
+ module GreenPepper
7
+
8
+ class ExampleContext
9
+ attr_accessor :index
10
+
11
+ def initialize(index = 0)
12
+ @index = index
13
+ end
14
+ end
15
+
16
+ class HtmlContext < ExampleContext
17
+ attr_accessor :nb_table, :first_table_index
18
+
19
+ def initialize(index = 0, first_table_index = 0, nb_table = 1)
20
+ super(index)
21
+ @first_table_index = first_table_index
22
+ @nb_table = nb_table
23
+ end
24
+ end
25
+
26
+ end #module GreenPepper
@@ -0,0 +1,347 @@
1
+ =begin
2
+ authors: Simon Mathieu (simon.math@gmail.com)
3
+ Sebastien Boisclair (sebboisclair@gmail.com)
4
+ date: March 3, 2009
5
+ =end
6
+ module GreenPepper
7
+
8
+ require 'singleton'
9
+ require 'date'
10
+ require 'greenpepper/grammar/arrayparser'
11
+
12
+ class TypeConverter
13
+ include Singleton
14
+
15
+ def initialize
16
+ @converters = []
17
+ end
18
+
19
+ def convert_string(string)
20
+ @converters.each { |type|
21
+ if type.can_parse? string
22
+ return type.convert.call(string)
23
+ end
24
+ }
25
+ string
26
+ end
27
+
28
+ def format_object(expected_string_format, object)
29
+ @converters.each { |type|
30
+ if type.can_parse? expected_string_format
31
+ return type.format.call(object, expected_string_format)
32
+ end
33
+ }
34
+ object.to_s
35
+ end
36
+
37
+ #Encapsulate all the type conversion logic for fixtures
38
+ def auto_convert_string(fixture, name, string)
39
+ parse_f = conversion_func name
40
+ if fixture.respond_to?(parse_f)
41
+ if string.is_a? Array
42
+ return fixture.send(parse_f, *string)
43
+ else
44
+ return fixture.send(parse_f, string)
45
+ end
46
+ else
47
+ if string.is_a? Array
48
+ return string.collect{|s| convert_string s}
49
+ else
50
+ return convert_string(string)
51
+ end
52
+ end
53
+ end
54
+
55
+ def auto_convert_object(fixture, name, expected_format, object)
56
+ format_f = format_func name
57
+ if fixture.respond_to?(format_f)
58
+ return fixture.send(format_f, object)
59
+ else
60
+ return format_object(expected_format, object)
61
+ end
62
+ end
63
+
64
+ def add_conversion_type(type)
65
+ @converters << type
66
+ end
67
+
68
+ private
69
+ def conversion_func(name)
70
+ ("parse_" + NameResolver.format_column_name(name)).to_sym
71
+ end
72
+
73
+ def format_func(name)
74
+ ("format_" + NameResolver.format_column_name(name)).to_sym
75
+ end
76
+ end
77
+
78
+ class TypeBase
79
+ def TypeBase.inherited(subclass)
80
+ TypeConverter.instance.add_conversion_type subclass
81
+ end
82
+
83
+ def self.can_parse?(str)
84
+ regex === str
85
+ end
86
+
87
+ def self.format
88
+ Proc.new{|object,expected_format| object.to_s}
89
+ end
90
+
91
+ end
92
+
93
+ class ErrorType < TypeBase
94
+
95
+ def self.regex
96
+ /^[\s]*error[\s]*$/i
97
+ end
98
+
99
+ def self.convert
100
+ Proc.new{|s| Exception.new}
101
+ end
102
+
103
+ def self.format
104
+ Proc.new{|object, expected_format|
105
+ if object.is_a? Exception
106
+ expected_format
107
+ else
108
+ object.to_s
109
+ end
110
+ }
111
+ end
112
+ end
113
+
114
+ class IntType < TypeBase
115
+
116
+ def self.regex
117
+ /^\s*-?[0-9]+\s*$/
118
+ end
119
+
120
+ def self.convert
121
+ Proc.new{|s| s.to_i}
122
+ end
123
+ end
124
+
125
+
126
+ class FloatType < TypeBase
127
+
128
+ def self.regex
129
+ /^\s*-?[0-9]*\.[0-9]+\s*$/
130
+ end
131
+
132
+ def self.convert
133
+ Proc.new{|s| s.to_f}
134
+ end
135
+
136
+ def self.format
137
+ Proc.new{ |b, expected_format|
138
+ if expected_format.match /^.[0-9]+$/
139
+ b.to_s[1..-1]
140
+ else
141
+ b.to_s
142
+ end
143
+ }
144
+ end
145
+ end
146
+
147
+ class BoolType < TypeBase
148
+ def self.regex
149
+ /^\s*(true|false|yes|no)\s*$/i
150
+ end
151
+
152
+ def self.convert
153
+ Proc.new{ |s|
154
+ (/true|yes/i =~ s) != nil
155
+ }
156
+ end
157
+
158
+ def self.format
159
+ Proc.new{ |b,expected_format|
160
+ yes = "yes"
161
+ no = "no"
162
+
163
+ case expected_format
164
+ when /^True|False$/
165
+ b.to_s.capitalize
166
+ when /^yes|no$/
167
+ b ? yes : no
168
+ when /^Yes|No$/
169
+ b ? yes.capitalize : no.capitalize
170
+ else
171
+ b.to_s
172
+ end
173
+ }
174
+ end
175
+ end
176
+
177
+ class BlankStringType < TypeBase
178
+ def self.regex
179
+ /^\s*blank\s*$/i
180
+ end
181
+
182
+ def self.convert
183
+ Proc.new{ |s|
184
+ ""
185
+ }
186
+ end
187
+
188
+ def self.format
189
+ Proc.new{ |s,expected_format|
190
+ expected_format
191
+ }
192
+ end
193
+ end
194
+
195
+ class NilType < TypeBase
196
+ def self.regex
197
+ /^\s*(nil|null|none|nothing|\s*)\s*$/i
198
+ end
199
+
200
+ def self.convert
201
+ Proc.new{ |s|
202
+ nil
203
+ }
204
+ end
205
+
206
+ def self.format
207
+ Proc.new{ |n,expected_format|
208
+ #The server return some weird unicode char when a cell is
209
+ #empty and since ruby 1.8 doesn't like unicode in regex, we
210
+ #have to do this ugly path here.
211
+ if /^\s*$/ === expected_format || expected_format[0] == 194
212
+ n.to_s
213
+ else
214
+ expected_format
215
+ end
216
+ }
217
+ end
218
+ end
219
+
220
+ class IsoDate < TypeBase
221
+ def self.regex
222
+ /^\s*(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])(\D?([01]\d|2[0-3])\D?([0-5]\d)\D?([0-5]\d)?\D?(\d{3})?([zZ]|([\+-])([01]\d|2[0-3])\D?([0-5]\d)?)?)?\s*$/
223
+ end
224
+
225
+ def self.convert
226
+ Proc.new{ |s|
227
+ begin
228
+ DateTime.parse(s)
229
+ rescue ArgumentError => exception
230
+ raise(GreenPepperTypeError.new,"Can't parse date #{s}")
231
+ end
232
+ }
233
+ end
234
+
235
+ def self.format
236
+ Proc.new{ |d,expected_format|
237
+ date_base_slash = d.year.to_s.rjust(4,"0") + "-" +
238
+ d.month.to_s.rjust(2,"0") + "-" + d.day.to_s.rjust(2,"0")
239
+ date_base_frontslash = d.year.to_s.rjust(4,"0") + "/" +
240
+ d.month.to_s.rjust(2,"0") + "/" + d.day.to_s.rjust(2,"0")
241
+ date_hour_min = d.hour.to_s.rjust(2,"0") + ":" +
242
+ d.min.to_s.rjust(2,"0")
243
+ date_extension = "Z"
244
+
245
+ case expected_format
246
+ when /^(\d+)\-(\d+)\-(\d+)\w(\d+):(\d+)\w$/
247
+ date_base_slash + "T" + date_hour_min + date_extension
248
+ when /^(\d+)\-(\d+)\-(\d+)\s(\d+):(\d+)$/
249
+ date_base_slash + " " + date_hour_min
250
+ when /^(\d+)\-(\d+)\-(\d+)\s(\d+):(\d+)\w$/
251
+ date_base_slash + " " + date_hour_min + date_extension
252
+ when /^(\d+)\-(\d+)\-(\d+)$/
253
+ date_base_slash
254
+ when /^(\d+)\/(\d+)\/(\d+)\w(\d+):(\d+)\w$/
255
+ date_base_frontslash + "T" + date_hour_min + date_extension
256
+ when /^(\d+)\/(\d+)\/(\d+)\s(\d+):(\d+)$/
257
+ date_base_frontslash + " " + date_hour_min
258
+ when /^(\d+)\/(\d+)\/(\d+)\s(\d+):(\d+)\w$/
259
+ date_base_frontslash + " " + date_hour_min + date_extension
260
+ when /^(\d+)\/(\d+)\/(\d+)$/
261
+ date_base_frontslash
262
+ else
263
+ d.to_s
264
+ end
265
+ }
266
+ end
267
+ end
268
+
269
+ class ExplicitStringType < TypeBase
270
+ def self.regex
271
+ /^\s*["'].*["']\s*$/
272
+ end
273
+
274
+ def self.convert
275
+ Proc.new{ |s| s[1..-2] }
276
+ end
277
+
278
+ def self.format
279
+ Proc.new{ |str,expected_format|
280
+ if (expected_format.index("'") == 0)
281
+ "'" + str.to_s + "'"
282
+ else
283
+ "\"" + str.to_s + "\""
284
+ end
285
+ }
286
+ end
287
+ end
288
+
289
+ class EmptyArrayType < TypeBase
290
+ def self.regex
291
+ /^\s*empty\s*$/i
292
+ end
293
+
294
+ def self.convert
295
+ Proc.new{ |s| [] }
296
+ end
297
+
298
+ def self.format
299
+ Proc.new{ |a,expected_format|
300
+ expected_format
301
+ }
302
+ end
303
+ end
304
+
305
+ class ArrayType < TypeBase
306
+ def self.regex
307
+ /^\s*(\[([^,]*,?)*\])|(([^,]+,)+[^,]+,?)\s*$/
308
+ end
309
+
310
+ def self.convert
311
+ Proc.new{ |s|
312
+ data = ArrayGrammarModule.parse(s)
313
+
314
+ data.collect{ |x|
315
+ TypeConverter.instance.convert_string x
316
+ }
317
+ }
318
+ end
319
+
320
+ def self.format
321
+ Proc.new{ |a,expected_format|
322
+ if a != nil
323
+ expected = ArrayGrammarModule.parse(expected_format)
324
+
325
+ a.each_index{|i|
326
+ a[i] = TypeConverter.instance.format_object expected[i],
327
+ a[i]
328
+ }
329
+
330
+ case expected_format
331
+ when /^\[([^,]*,)*\]$/
332
+ "[" + a.join(",") + ",]"
333
+ when /^\[([^,]*,?)*\]$/
334
+ "[" + a.join(",") + "]"
335
+ when /^([^,]+,)+[^,]+,$/
336
+ a.join(",") + ","
337
+ else
338
+ a.join(",")
339
+ end
340
+ else
341
+ ""
342
+ end
343
+ }
344
+ end
345
+ end
346
+
347
+ end #module GreenPepper