gorp 0.26.2 → 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -1,7 +1,6 @@
1
1
  Manifest
2
2
  README
3
3
  Rakefile
4
- gorp.gemspec
5
4
  lib/gorp.rb
6
5
  lib/gorp/commands.rb
7
6
  lib/gorp/edit.rb
data/Rakefile CHANGED
@@ -21,15 +21,9 @@ Echoe.new('gorp', Gorp::VERSION::STRING) do |p|
21
21
  p.dependencies = %w(
22
22
  builder
23
23
  bundler
24
- erubis
25
24
  i18n
26
25
  rack
27
- rack-mount
28
- rack-test
29
26
  rake
30
- thor
31
- sqlite3-ruby
32
- tzinfo
33
27
  )
34
28
  # Does not include mail -- as it depends on active_support
35
29
  # test-unit -- incompatible with i18n one hash required (testrunner.rb:116)
@@ -1,70 +1,44 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{gorp}
5
- s.version = "0.26.2"
4
+ s.name = "gorp"
5
+ s.version = "0.27.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Sam Ruby"]
9
- s.date = %q{2010-12-08}
10
- s.description = %q{ Enables the creation of scenarios that involve creating a rails project,
11
- starting and stoppping of servers, generating projects, editing files,
12
- issuing http requests, running of commands, etc. Output is captured as
13
- a single HTML file that can be viewed locally or uploaded.
14
-
15
- Additionally, there is support for verification, in the form of defining
16
- assertions based on selections (typically CSS) against the generated HTML.
17
- }
18
- s.email = %q{rubys@intertwingly.net}
9
+ s.date = "2011-10-21"
10
+ s.description = " Enables the creation of scenarios that involve creating a rails project,\n starting and stoppping of servers, generating projects, editing files,\n issuing http requests, running of commands, etc. Output is captured as\n a single HTML file that can be viewed locally or uploaded.\n\n Additionally, there is support for verification, in the form of defining\n assertions based on selections (typically CSS) against the generated HTML.\n"
11
+ s.email = "rubys@intertwingly.net"
19
12
  s.extra_rdoc_files = ["README", "lib/gorp.rb", "lib/gorp/commands.rb", "lib/gorp/edit.rb", "lib/gorp/env.rb", "lib/gorp/net.rb", "lib/gorp/output.css", "lib/gorp/output.rb", "lib/gorp/rails.env", "lib/gorp/rails.rb", "lib/gorp/test.rb", "lib/gorp/xml.rb", "lib/version.rb"]
20
- s.files = ["Manifest", "README", "Rakefile", "gorp.gemspec", "lib/gorp.rb", "lib/gorp/commands.rb", "lib/gorp/edit.rb", "lib/gorp/env.rb", "lib/gorp/net.rb", "lib/gorp/output.css", "lib/gorp/output.rb", "lib/gorp/rails.env", "lib/gorp/rails.rb", "lib/gorp/test.rb", "lib/gorp/xml.rb", "lib/version.rb"]
21
- s.homepage = %q{http://github.com/rubys/gorp}
13
+ s.files = ["Manifest", "README", "Rakefile", "lib/gorp.rb", "lib/gorp/commands.rb", "lib/gorp/edit.rb", "lib/gorp/env.rb", "lib/gorp/net.rb", "lib/gorp/output.css", "lib/gorp/output.rb", "lib/gorp/rails.env", "lib/gorp/rails.rb", "lib/gorp/test.rb", "lib/gorp/xml.rb", "lib/version.rb", "gorp.gemspec"]
14
+ s.homepage = "http://github.com/rubys/gorp"
22
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Gorp", "--main", "README"]
23
16
  s.require_paths = ["lib"]
24
- s.rubyforge_project = %q{gorp}
25
- s.rubygems_version = %q{1.3.7}
26
- s.summary = %q{Rails scenario testing support library}
17
+ s.rubyforge_project = "gorp"
18
+ s.rubygems_version = "1.8.11"
19
+ s.summary = "Rails scenario testing support library"
27
20
 
28
21
  if s.respond_to? :specification_version then
29
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
30
22
  s.specification_version = 3
31
23
 
32
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
33
25
  s.add_runtime_dependency(%q<builder>, [">= 0"])
34
26
  s.add_runtime_dependency(%q<bundler>, [">= 0"])
35
- s.add_runtime_dependency(%q<erubis>, [">= 0"])
36
27
  s.add_runtime_dependency(%q<i18n>, [">= 0"])
37
28
  s.add_runtime_dependency(%q<rack>, [">= 0"])
38
- s.add_runtime_dependency(%q<rack-mount>, [">= 0"])
39
- s.add_runtime_dependency(%q<rack-test>, [">= 0"])
40
29
  s.add_runtime_dependency(%q<rake>, [">= 0"])
41
- s.add_runtime_dependency(%q<thor>, [">= 0"])
42
- s.add_runtime_dependency(%q<sqlite3-ruby>, [">= 0"])
43
- s.add_runtime_dependency(%q<tzinfo>, [">= 0"])
44
30
  else
45
31
  s.add_dependency(%q<builder>, [">= 0"])
46
32
  s.add_dependency(%q<bundler>, [">= 0"])
47
- s.add_dependency(%q<erubis>, [">= 0"])
48
33
  s.add_dependency(%q<i18n>, [">= 0"])
49
34
  s.add_dependency(%q<rack>, [">= 0"])
50
- s.add_dependency(%q<rack-mount>, [">= 0"])
51
- s.add_dependency(%q<rack-test>, [">= 0"])
52
35
  s.add_dependency(%q<rake>, [">= 0"])
53
- s.add_dependency(%q<thor>, [">= 0"])
54
- s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
55
- s.add_dependency(%q<tzinfo>, [">= 0"])
56
36
  end
57
37
  else
58
38
  s.add_dependency(%q<builder>, [">= 0"])
59
39
  s.add_dependency(%q<bundler>, [">= 0"])
60
- s.add_dependency(%q<erubis>, [">= 0"])
61
40
  s.add_dependency(%q<i18n>, [">= 0"])
62
41
  s.add_dependency(%q<rack>, [">= 0"])
63
- s.add_dependency(%q<rack-mount>, [">= 0"])
64
- s.add_dependency(%q<rack-test>, [">= 0"])
65
42
  s.add_dependency(%q<rake>, [">= 0"])
66
- s.add_dependency(%q<thor>, [">= 0"])
67
- s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
68
- s.add_dependency(%q<tzinfo>, [">= 0"])
69
43
  end
70
44
  end
@@ -1,6 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'builder'
3
3
  require 'time'
4
+ require 'thread'
4
5
 
5
6
  module Gorp
6
7
  module Commands
@@ -175,8 +176,9 @@ module Gorp
175
176
 
176
177
  if args == 'rake db:migrate'
177
178
  Dir.chdir 'db/migrate' do
178
- date = '20110211000000'
179
- Dir['[0-9]*'].sort_by {|fn| fn=~/201102/ ? fn : 'x'+fn}.each do |file|
179
+ date = '20110711000000'
180
+ mask = Regexp.new("^#{date[0..-4]}")
181
+ Dir['[0-9]*'].sort_by {|fn| fn=~mask ? fn : 'x'+fn}.each do |file|
180
182
  file =~ /^([0-9]*)_(.*)$/
181
183
  FileUtils.mv file, "#{date}_#{$2}" unless $1 == date.next!
182
184
  $x.pre "mv #{file} #{date}_#{$2}" unless $1 == date
@@ -34,9 +34,23 @@ module Gorp
34
34
  module StringEditingFunctions
35
35
  def highlight
36
36
  if self =~ /^\s*<[%!\w].*>/
37
+ # HTML, possibly XML
37
38
  start = '<!-- START_HIGHLIGHT -->'
38
39
  close = '<!-- END_HIGHLIGHT -->'
40
+ elsif self =~ /^\s*[.#]\w+[, ].*\{$/
41
+ # CSS
42
+ start = '/* START_HIGHLIGHT */'
43
+ close = '/* END_HIGHLIGHT */'
44
+ elsif self =~ /;\s*\}?$/
45
+ # JavaScript
46
+ start = '//#START_HIGHLIGHT'
47
+ close = '//#END_HIGHLIGHT'
48
+ elsif self =~ /->$/
49
+ # CoffeeScript
50
+ start = '//#START_HIGHLIGHT'
51
+ close = '//#END_HIGHLIGHT'
39
52
  else
53
+ # Other, most likely Ruby
40
54
  start = '#START_HIGHLIGHT'
41
55
  close = '#END_HIGHLIGHT'
42
56
  end
@@ -54,6 +68,9 @@ module Gorp
54
68
  if self =~ /^\s*<[%!\w].*>/
55
69
  start = "<!-- START:#{name} -->"
56
70
  close = "<!-- END:#{name} -->"
71
+ elsif self =~ /;\s*\}?$/
72
+ start = "//#START:#{name}"
73
+ close = "//#END:#{name}"
57
74
  else
58
75
  start = "#START:#{name}"
59
76
  close = "#END:#{name}"
@@ -103,11 +120,13 @@ module Gorp
103
120
  end
104
121
 
105
122
  def clear_highlights
106
- self.gsub! /^\s*(#|<!--)\s*(START|END)_HIGHLIGHT(\s*-->)?\n/, ''
123
+ self.gsub! /^ *(\/\/#)\s*(START|END)_HIGHLIGHT\n/, ''
124
+ self.gsub! /^\s*(#|<!--|\/\*)\s*(START|END)_HIGHLIGHT\s*(-->|\*\/)?\n/, ''
107
125
  end
108
126
 
109
127
  def clear_all_marks
110
- self.gsub! /^\s*(#|<!--)\s*(START|END)(_HIGHLIGHT|:\w+)(\s*-->)?\n/, ''
128
+ self.gsub! /^ *(\/\/#)\s*(START|END)(_HIGHLIGHT|:\w+)\n/, ''
129
+ self.gsub! /^\s*(#|<!--|\/\*|\/\/#)\s*(START|END)(_HIGHLIGHT|:\w+)\s*(-->|\*\/)?\n/, ''
111
130
  end
112
131
 
113
132
  def msub pattern, replacement, option=nil
@@ -117,6 +136,8 @@ module Gorp
117
136
  elsif option.respond_to? :keys
118
137
  replacement.extend Gorp::StringEditingFunctions
119
138
  replacement.mark(option[:mark])
139
+ elsif option == :optional
140
+ return unless match(pattern)
120
141
  end
121
142
 
122
143
  if replacement =~ /\\[1-9]/
@@ -20,7 +20,11 @@ end
20
20
 
21
21
  # base directories
22
22
  $BASE=File.expand_path(File.dirname(caller.last.split(':').first)) unless $BASE
23
+ if $EDITION
24
+ $DATA = File.join($BASE,$EDITION,'data')
25
+ else
23
26
  $DATA = File.join($BASE,'data')
27
+ end
24
28
  $CODE = File.join($DATA,'code')
25
29
 
26
30
  # work directory
@@ -32,29 +36,27 @@ else
32
36
  end
33
37
 
34
38
  # deduce environment based on provided Gemfile
35
- unless ENV['GORP_RAILS']
36
- gemfile = "#{$BASE}/Gemfile" if File.exist? "#{$BASE}/Gemfile"
37
- gemfile = "#{$WORK}/Gemfile" if File.exist? "#{$WORK}/Gemfile"
38
- if gemfile
39
- libs = ENV['RUBYLIB'].to_s.split(File::PATH_SEPARATOR)
40
- open(gemfile) do |file|
41
- pattern = /^gem\s+['"](\w+)['"],\s*:path\s*=>\s*['"](.*?)['"]/
42
- file.read.scan(pattern).each do |name,path|
43
- if name == 'rails'
44
- ENV['GORP_RAILS'] ||= path
45
- else
46
- $: << "#{path}/lib"
47
- libs << "#{path}/lib"
48
- end
39
+ gemfile = "#{$BASE}/Gemfile" if File.exist? "#{$BASE}/Gemfile"
40
+ gemfile = "#{$WORK}/Gemfile" if File.exist? "#{$WORK}/Gemfile"
41
+ if gemfile
42
+ open(gemfile) do |file|
43
+ pattern = /^gem\s+['"](\w+)['"],\s*:path\s*=>\s*['"](.*?)['"]/
44
+ file.read.scan(pattern).each do |name,path|
45
+ if name == 'rails'
46
+ ENV['GORP_RAILS'] ||= path
47
+ else
48
+ $: << "#{path}/lib"
49
49
  end
50
50
  end
51
- ENV['RUBYLIB'] = libs.join(File::PATH_SEPARATOR)
52
- ENV.delete 'BUNDLE_GEMFILE'
51
+ end
52
+
53
+ Dir.chdir(File.dirname(gemfile)) do
54
+ require 'bundler/setup'
53
55
  end
54
56
  end
55
57
 
56
- require 'rbconfig'
57
- $ruby = File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])
58
+ config = RbConfig::CONFIG
59
+ $ruby = File.join(config["bindir"], config["RUBY_INSTALL_NAME"])
58
60
 
59
61
  FileUtils.mkdir_p $WORK
60
62
 
@@ -63,6 +65,9 @@ module Gorp
63
65
  extend Commands
64
66
  $x.pre Time.now.httpdate, :class=>'stdout'
65
67
 
68
+ cmd "echo $PATH"
69
+ cmd "node -v"
70
+
66
71
  cmd "#{$ruby} -v"
67
72
  cmd 'gem -v'
68
73
  Dir.chdir(File.join($WORK, $rails_app.to_s)) do
@@ -70,6 +70,7 @@ def snap response, form=nil
70
70
  attrs = {:class => 'body', :title => title}
71
71
  attrs[:class] = 'traceback' if response.code == '500'
72
72
  attrs[:id] = body['id'] if body['id']
73
+ attrs[:class] += ' ' +body['class'] if body['class']
73
74
  $x.div(attrs) do
74
75
  body.children.each do |child|
75
76
  $x << child.to_xml unless child.instance_of?(Comment)
@@ -103,14 +103,18 @@ module Gorp
103
103
  # determine how to invoke rails
104
104
  rails = Gorp.which_rails($rails)
105
105
  rails += ' new' if `#{rails} -v` !~ /Rails 2/
106
- if `ruby -v` =~ /1\.8/
106
+ opt = ''
107
+ if File.exist? 'Gemfile'
108
+ rails = "bundle exec " + rails
109
+ opt += ' --skip-bundle'
110
+ opt += ' --dev' if File.read('Gemfile') =~ /gem ['"]rails['"], :path/
111
+ elsif `ruby -v` =~ /1\.8/
107
112
  rails.sub! /^/, 'ruby ' unless rails =~ /^ruby /
108
113
  rails.sub! 'ruby ', 'ruby -rubygems '
109
114
  end
110
115
 
111
- opt = (ARGV.include?('--dev') ? ' --dev' : '')
112
116
  $x.pre "#{rails.gsub('/',FILE_SEPARATOR)} #{name}#{opt}", :class=>'stdin'
113
- popen3 "#{rails} #{name}#{opt}"
117
+ popen3 "#{rails} #{name}#{opt.sub(' --dev','')}"
114
118
 
115
119
  # canonicalize the reference to Ruby
116
120
  Dir["#{name}/script/**/*"].each do |script|
@@ -135,8 +139,17 @@ module Gorp
135
139
  name = path.split(File::SEPARATOR).last
136
140
  next if name == 'gorp'
137
141
  if File.exist?(File.join(path, "/#{name}.gemspec"))
138
- gemfile[/gem 'rails',.*\n()/,1] =
139
- "gem #{name.inspect}, :path => #{path.inspect}\n"
142
+ if gemfile =~ /^\s*gem ['"]#{name}['"],\s*:git/
143
+ gemfile[/^\s*gem ['"]#{name}['"],\s*(:git\s*=>\s*).*/,1] =
144
+ ":path => #{path.inspect} # "
145
+ elsif gemfile =~ /^\s*gem ['"]#{name}['"],/
146
+ gemfile[/^\s*gem ['"]#{name}['"],\s*()/,1] =
147
+ ":path => #{path.inspect} # "
148
+ else
149
+ gemfile.sub!(/(^\s*gem ['"]#{name}['"])/) {|line| '# ' + line}
150
+ gemfile[/gem 'rails',.*\n()/,1] =
151
+ "gem #{name.inspect}, :path => #{path.inspect}\n"
152
+ end
140
153
  end
141
154
  end
142
155
  gemfile[/^()source/, 1] = '# '
@@ -228,6 +241,7 @@ module Gorp
228
241
  end
229
242
 
230
243
  if $server
244
+ sleep 3
231
245
  # wait for server to start
232
246
  60.times do
233
247
  sleep 0.5
@@ -1,17 +1,15 @@
1
1
  gem 'test-unit'
2
2
  require 'test/unit'
3
- require 'builder'
4
3
  require 'gorp/env'
5
4
  require 'gorp/rails'
6
5
  require 'gorp/commands'
6
+ require 'builder'
7
7
 
8
8
  class Gorp::TestCase < Test::Unit::TestCase
9
9
  def self.suite
10
10
  # Deferred loading of Rails infrastructure
11
11
  if File.exist? "#{$WORK}/.bundle/environment.rb"
12
12
  require "#{$WORK}/.bundle/environment.rb"
13
- elsif File.exist? "#{$WORK}/Gemfile"
14
- Dir.chdir($WORK) { require 'bundler/setup' }
15
13
  end
16
14
 
17
15
  require 'active_support'
@@ -140,7 +138,7 @@ class Gorp::TestCase < Test::Unit::TestCase
140
138
  @@base = Object.new.extend(Gorp::Commands)
141
139
  include Gorp::Commands
142
140
 
143
- %w(cmd get post rake ruby console).each do |method|
141
+ %w(cmd get post rake ruby console db).each do |method|
144
142
  define_method(method) do |*args, &block|
145
143
  before = $x.target.length
146
144
  @@base.send method, *args
@@ -1,8 +1,8 @@
1
1
  module Gorp
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 26
5
- TINY = 2
4
+ MINOR = 27
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
metadata CHANGED
@@ -2,12 +2,12 @@
2
2
  name: gorp
3
3
  version: !ruby/object:Gem::Version
4
4
  hash: 115
5
- prerelease: false
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 26
9
- - 2
10
- version: 0.26.2
8
+ - 27
9
+ - 0
10
+ version: 0.27.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sam Ruby
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-08 00:00:00 -05:00
19
- default_executable:
18
+ date: 2011-10-21 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: builder
@@ -47,7 +46,7 @@ dependencies:
47
46
  type: :runtime
48
47
  version_requirements: *id002
49
48
  - !ruby/object:Gem::Dependency
50
- name: erubis
49
+ name: i18n
51
50
  prerelease: false
52
51
  requirement: &id003 !ruby/object:Gem::Requirement
53
52
  none: false
@@ -61,7 +60,7 @@ dependencies:
61
60
  type: :runtime
62
61
  version_requirements: *id003
63
62
  - !ruby/object:Gem::Dependency
64
- name: i18n
63
+ name: rack
65
64
  prerelease: false
66
65
  requirement: &id004 !ruby/object:Gem::Requirement
67
66
  none: false
@@ -75,7 +74,7 @@ dependencies:
75
74
  type: :runtime
76
75
  version_requirements: *id004
77
76
  - !ruby/object:Gem::Dependency
78
- name: rack
77
+ name: rake
79
78
  prerelease: false
80
79
  requirement: &id005 !ruby/object:Gem::Requirement
81
80
  none: false
@@ -88,90 +87,6 @@ dependencies:
88
87
  version: "0"
89
88
  type: :runtime
90
89
  version_requirements: *id005
91
- - !ruby/object:Gem::Dependency
92
- name: rack-mount
93
- prerelease: false
94
- requirement: &id006 !ruby/object:Gem::Requirement
95
- none: false
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- hash: 3
100
- segments:
101
- - 0
102
- version: "0"
103
- type: :runtime
104
- version_requirements: *id006
105
- - !ruby/object:Gem::Dependency
106
- name: rack-test
107
- prerelease: false
108
- requirement: &id007 !ruby/object:Gem::Requirement
109
- none: false
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- hash: 3
114
- segments:
115
- - 0
116
- version: "0"
117
- type: :runtime
118
- version_requirements: *id007
119
- - !ruby/object:Gem::Dependency
120
- name: rake
121
- prerelease: false
122
- requirement: &id008 !ruby/object:Gem::Requirement
123
- none: false
124
- requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- hash: 3
128
- segments:
129
- - 0
130
- version: "0"
131
- type: :runtime
132
- version_requirements: *id008
133
- - !ruby/object:Gem::Dependency
134
- name: thor
135
- prerelease: false
136
- requirement: &id009 !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- hash: 3
142
- segments:
143
- - 0
144
- version: "0"
145
- type: :runtime
146
- version_requirements: *id009
147
- - !ruby/object:Gem::Dependency
148
- name: sqlite3-ruby
149
- prerelease: false
150
- requirement: &id010 !ruby/object:Gem::Requirement
151
- none: false
152
- requirements:
153
- - - ">="
154
- - !ruby/object:Gem::Version
155
- hash: 3
156
- segments:
157
- - 0
158
- version: "0"
159
- type: :runtime
160
- version_requirements: *id010
161
- - !ruby/object:Gem::Dependency
162
- name: tzinfo
163
- prerelease: false
164
- requirement: &id011 !ruby/object:Gem::Requirement
165
- none: false
166
- requirements:
167
- - - ">="
168
- - !ruby/object:Gem::Version
169
- hash: 3
170
- segments:
171
- - 0
172
- version: "0"
173
- type: :runtime
174
- version_requirements: *id011
175
90
  description: " Enables the creation of scenarios that involve creating a rails project,\n starting and stoppping of servers, generating projects, editing files,\n issuing http requests, running of commands, etc. Output is captured as\n a single HTML file that can be viewed locally or uploaded.\n\n Additionally, there is support for verification, in the form of defining\n assertions based on selections (typically CSS) against the generated HTML.\n"
176
91
  email: rubys@intertwingly.net
177
92
  executables: []
@@ -196,7 +111,6 @@ files:
196
111
  - Manifest
197
112
  - README
198
113
  - Rakefile
199
- - gorp.gemspec
200
114
  - lib/gorp.rb
201
115
  - lib/gorp/commands.rb
202
116
  - lib/gorp/edit.rb
@@ -209,7 +123,7 @@ files:
209
123
  - lib/gorp/test.rb
210
124
  - lib/gorp/xml.rb
211
125
  - lib/version.rb
212
- has_rdoc: true
126
+ - gorp.gemspec
213
127
  homepage: http://github.com/rubys/gorp
214
128
  licenses: []
215
129
 
@@ -245,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
159
  requirements: []
246
160
 
247
161
  rubyforge_project: gorp
248
- rubygems_version: 1.3.7
162
+ rubygems_version: 1.8.11
249
163
  signing_key:
250
164
  specification_version: 3
251
165
  summary: Rails scenario testing support library