newjs 1.0.0

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 (69) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +68 -0
  4. data/README.txt +9 -0
  5. data/Rakefile +4 -0
  6. data/app_generators/newjs/USAGE +9 -0
  7. data/app_generators/newjs/newjs_generator.rb +113 -0
  8. data/app_generators/newjs/templates/History.txt.erb +4 -0
  9. data/app_generators/newjs/templates/License.txt.erb +20 -0
  10. data/app_generators/newjs/templates/README.txt +1 -0
  11. data/app_generators/newjs/templates/Rakefile.erb +82 -0
  12. data/app_generators/newjs/templates/config/javascript_test_autotest.yml.sample +15 -0
  13. data/app_generators/newjs/templates/lib/jstest.rb +382 -0
  14. data/app_generators/newjs/templates/lib/protodoc.rb +36 -0
  15. data/app_generators/newjs/templates/script/js_autotest +1 -0
  16. data/app_generators/newjs/templates/script/rstakeout +98 -0
  17. data/app_generators/newjs/templates/src/HEADER.erb +8 -0
  18. data/app_generators/newjs/templates/src/library.js.erb +7 -0
  19. data/app_generators/newjs/templates/tasks/environment.rake +7 -0
  20. data/app_generators/newjs/templates/tasks/javascript_test_autotest_tasks.rake +44 -0
  21. data/app_generators/newjs/templates/test/assets/prototype.js +4236 -0
  22. data/app_generators/newjs/templates/test/assets/unittest.css +50 -0
  23. data/app_generators/newjs/templates/test/assets/unittest.js +556 -0
  24. data/bin/newjs +17 -0
  25. data/config/hoe.rb +75 -0
  26. data/config/requirements.rb +17 -0
  27. data/javascript_test_generators/javascript_test/USAGE +2 -0
  28. data/javascript_test_generators/javascript_test/javascript_test_generator.rb +54 -0
  29. data/javascript_test_generators/javascript_test/templates/test/test.html.erb +58 -0
  30. data/lib/newjs.rb +7 -0
  31. data/lib/newjs/autotest.rb +3 -0
  32. data/lib/newjs/autotest/javascript_test_autotest.rb +22 -0
  33. data/lib/newjs/autotest/javascript_test_autotest/config.rb +20 -0
  34. data/lib/newjs/autotest/javascript_test_ext.rb +29 -0
  35. data/lib/newjs/jstest.rb +382 -0
  36. data/lib/newjs/version.rb +9 -0
  37. data/log/debug.log +0 -0
  38. data/newjs_generators/install_website/USAGE +5 -0
  39. data/newjs_generators/install_website/install_website_generator.rb +79 -0
  40. data/newjs_generators/install_website/templates/script/txt2html +74 -0
  41. data/newjs_generators/install_website/templates/script/win_script.cmd +1 -0
  42. data/newjs_generators/install_website/templates/tasks/website.rake +17 -0
  43. data/newjs_generators/install_website/templates/website/index.html +11 -0
  44. data/newjs_generators/install_website/templates/website/index.txt +37 -0
  45. data/newjs_theme_generators/plain_theme/USAGE +0 -0
  46. data/newjs_theme_generators/plain_theme/plain_theme_generator.rb +54 -0
  47. data/newjs_theme_generators/plain_theme/templates/website/javascripts/rounded_corners_lite.inc.js +285 -0
  48. data/newjs_theme_generators/plain_theme/templates/website/stylesheets/screen.css +138 -0
  49. data/newjs_theme_generators/plain_theme/templates/website/template.html.erb +48 -0
  50. data/script/destroy +14 -0
  51. data/script/generate +14 -0
  52. data/script/txt2html +74 -0
  53. data/setup.rb +1585 -0
  54. data/tasks/deployment.rake +34 -0
  55. data/tasks/environment.rake +7 -0
  56. data/tasks/website.rake +17 -0
  57. data/test/test_generator_helper.rb +20 -0
  58. data/test/test_helper.rb +4 -0
  59. data/test/test_install_website_generator.rb +39 -0
  60. data/test/test_javascript_test_generator.rb +43 -0
  61. data/test/test_newjs_generator.rb +63 -0
  62. data/test/test_plain_theme_generator.rb +37 -0
  63. data/website/images/example-unittest-log.jpg +0 -0
  64. data/website/index.html +271 -0
  65. data/website/index.txt +181 -0
  66. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  67. data/website/stylesheets/screen.css +138 -0
  68. data/website/template.html.erb +48 -0
  69. metadata +168 -0
data/bin/newjs ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby -wKU
2
+
3
+ require 'rubygems'
4
+ require 'rubigen'
5
+
6
+ if %w(-v --version).include? ARGV.first
7
+ require 'newjs/version'
8
+ puts "#{File.basename($0)} #{Newjs::VERSION::STRING}"
9
+ exit(0)
10
+ end
11
+
12
+ require 'rubigen/scripts/generate'
13
+ source = RubiGen::PathSource.new(:application,
14
+ File.join(File.dirname(__FILE__), "../app_generators"))
15
+ RubiGen::Base.reset_sources
16
+ RubiGen::Base.append_sources source
17
+ RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'newjs')
data/config/hoe.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'newjs/version'
2
+
3
+ AUTHOR = 'Dr Nic Williams' # can also be an array of Authors
4
+ EMAIL = "drnicwilliams@gmail.com"
5
+ GEM_NAME = 'newjs' # what ppl will type to install your gem
6
+ RUBYFORGE_PROJECT = 'newjs' # The unix name for your project
7
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
8
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
9
+
10
+ @config_file = "~/.rubyforge/user-config.yml"
11
+ @config = nil
12
+ RUBYFORGE_USERNAME = "unknown"
13
+ def rubyforge_username
14
+ unless @config
15
+ begin
16
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
17
+ rescue
18
+ puts <<-EOS
19
+ ERROR: No rubyforge config file found: #{@config_file}
20
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
21
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
22
+ EOS
23
+ exit
24
+ end
25
+ end
26
+ RUBYFORGE_USERNAME.replace @config["username"]
27
+ end
28
+
29
+
30
+ REV = nil
31
+ # UNCOMMENT IF REQUIRED:
32
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
33
+ VERS = Newjs::VERSION::STRING + (REV ? ".#{REV}" : "")
34
+ RDOC_OPTS = ['--quiet', '--title', 'newjs documentation',
35
+ "--opname", "index.html",
36
+ "--line-numbers",
37
+ "--main", "README",
38
+ "--inline-source"]
39
+
40
+ class Hoe
41
+ def extra_deps
42
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
43
+ @extra_deps
44
+ end
45
+ end
46
+
47
+ # Generate all the Rake tasks
48
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
49
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
50
+ p.developer(AUTHOR, EMAIL)
51
+ p.description = p.paragraphs_of("README.txt", 0..2).join("\n\n")
52
+ p.summary = p.paragraphs_of("README.txt", 0..0).join("\n\n")
53
+ p.url = HOMEPATH
54
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
55
+ p.test_globs = ["test/**/test_*.rb"]
56
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
57
+
58
+ # == Optional
59
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
60
+ p.extra_deps = [
61
+ ['hoe', '>=1.5.0'],
62
+ ['RedCloth','>=3.0.4'],
63
+ ['syntax','>=1.0.0'],
64
+ ['activesupport','>=2.0.2'],
65
+ ['rubigen','>=1.2.0']
66
+ ]
67
+
68
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
69
+
70
+ end
71
+
72
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
73
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
74
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
75
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'newjs'
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Creates an HTML test file for a JavaScript library.
@@ -0,0 +1,54 @@
1
+ class JavascriptTestGenerator < RubiGen::Base
2
+
3
+ attr_reader :name, :library_name
4
+
5
+ def initialize(runtime_args, runtime_options = {})
6
+ super
7
+ usage if args.empty?
8
+ @name = args.shift
9
+ @library_name = args.shift || name
10
+ extract_options
11
+ end
12
+
13
+ def manifest
14
+ record do |m|
15
+ # Ensure appropriate folder(s) exists
16
+ m.directory 'test'
17
+
18
+ # Create stubs
19
+ m.template "test/test.html.erb", "test/#{name}_test.html"
20
+ end
21
+ end
22
+
23
+ protected
24
+ def banner
25
+ <<-EOS
26
+ Creates an HTML test file for a JavaScript library.
27
+
28
+ USAGE: #{$0} #{spec.name} name [library_name]"
29
+
30
+ NOTES:
31
+ * name - creates a file test/name_test.html
32
+ * library_name - is for a file src/library_name.js
33
+
34
+ EOS
35
+ end
36
+
37
+ def add_options!(opts)
38
+ # opts.separator ''
39
+ # opts.separator 'Options:'
40
+ # For each option below, place the default
41
+ # at the top of the file next to "default_options"
42
+ # opts.on("-a", "--author=\"Your Name\"", String,
43
+ # "Some comment about this option",
44
+ # "Default: none") { |options[:author]| }
45
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
46
+ end
47
+
48
+ def extract_options
49
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
50
+ # Templates can access these value via the attr_reader-generated methods, but not the
51
+ # raw instance variable value.
52
+ # @author = options[:author]
53
+ end
54
+ end
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <title>JavaScript unit test file</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <script src="assets/prototype.js" type="text/javascript"></script>
8
+ <script src="assets/unittest.js" type="text/javascript"></script>
9
+
10
+ <script src="../src/<%= library_name %>.js" type="text/javascript"></script>
11
+
12
+ <link rel="stylesheet" href="assets/unittest.css" type="text/css" />
13
+ </head>
14
+ <body>
15
+
16
+ <div id="content">
17
+
18
+ <div id="header">
19
+ <h1>JavaScript unit test file</h1>
20
+ <p>
21
+ This file tests <strong><%= library_name %>.js</strong>.
22
+ </p>
23
+ </div>
24
+
25
+ <!-- Log output (one per Runner, via {testLog: "testlog"} option)-->
26
+ <div id="testlog"></div>
27
+
28
+ <!-- Put sample/test html here -->
29
+ <div id="sample"></div>
30
+ </div>
31
+
32
+ <script type="text/javascript">
33
+ // <![CDATA[
34
+
35
+ new Test.Unit.Runner({
36
+ // replace this with your real tests
37
+ setup: function() {
38
+
39
+ },
40
+
41
+ teardown: function() {
42
+
43
+ },
44
+
45
+ testTruth: function() { with(this) {
46
+ assert(true);
47
+ }}
48
+
49
+ }, {testLog: "testlog"});
50
+ // For each Test.UnitRunner instance, specify the element id where results will be
51
+ // published; e.g. <div id="testlog"/> above.
52
+ // That is, you can have multiple "new Test.Unit.Runner() { ... }" on this page, just
53
+ // create more <div id="testlog2"></div> etc, and pass the element id to the hash above:
54
+ // e.g. {testLog: "testlog2"}
55
+ // ]]>
56
+ </script>
57
+ </body>
58
+ </html>
data/lib/newjs.rb ADDED
@@ -0,0 +1,7 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ module Newjs
4
+
5
+ end
6
+
7
+ require 'newjs/jstest'
@@ -0,0 +1,3 @@
1
+ %w[javascript_test_autotest javascript_test_ext].each do |file|
2
+ require File.dirname(__FILE__) + "/autotest/" + file
3
+ end
@@ -0,0 +1,22 @@
1
+ module JavascriptTestAutotest
2
+ class Browser
3
+ class << self
4
+ def browser(browser, path)
5
+ case(browser.to_sym)
6
+ when :firefox
7
+ FirefoxBrowser.new(path)
8
+ when :safari
9
+ SafariBrowser.new(path)
10
+ when :ie
11
+ IEBrowser.new(path)
12
+ when :konqueror
13
+ KonquerorBrowser.new(path)
14
+ else
15
+ browser
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ require File.dirname(__FILE__) + "/javascript_test_autotest/config"
@@ -0,0 +1,20 @@
1
+ require 'yaml'
2
+
3
+ class JavascriptTestAutotest::Config
4
+ def self.get var, default = nil
5
+ value = configs[var.to_s]
6
+ value ||= default
7
+ value ||= yield if block_given?
8
+ value
9
+ end
10
+
11
+ private
12
+ def self.configs
13
+ unless defined? @@configs
14
+ file = File.expand_path("#{APP_ROOT}/config/javascript_test_autotest.yml")
15
+ @@configs = File.exist?(file) ? YAML.load_file(file) : {}
16
+ end
17
+ @@configs
18
+ end
19
+
20
+ end
@@ -0,0 +1,29 @@
1
+ class Browser
2
+ def initialize(path)
3
+ unless path == :ignore
4
+ @path = path
5
+ puts "WARNING: #{self} does not exist at #{@path}" unless File.exists?(@path)
6
+ end
7
+ end
8
+ end
9
+
10
+ if Browser.new(:ignore).macos?
11
+ class SafariBrowser
12
+ def setup; end # no need to create new Browser, as open command automates this
13
+ def visit(file)
14
+ @path ||= 'Safari.app'
15
+ `open #{file} -a #{@path} -g`
16
+ end
17
+ def teardown; end # no need to destroy Browser
18
+ end
19
+
20
+ class FirefoxBrowser
21
+ def setup; end # no need to create new Browser, as open command automates this
22
+ def visit(file)
23
+ @path ||= 'Safari.app'
24
+ puts "open #{file} -a #{@path} -g"
25
+ `open #{file} -a #{@path} -g`
26
+ end
27
+ def teardown; end # no need to destroy Browser
28
+ end
29
+ end
@@ -0,0 +1,382 @@
1
+ require 'rake/tasklib'
2
+ require 'thread'
3
+ require 'webrick'
4
+ require 'fileutils'
5
+ include FileUtils
6
+
7
+ class Browser
8
+ def supported?; true; end
9
+ def setup ; end
10
+ def open(url) ; end
11
+ def teardown ; end
12
+
13
+ def host
14
+ require 'rbconfig'
15
+ Config::CONFIG['host']
16
+ end
17
+
18
+ def macos?
19
+ host.include?('darwin')
20
+ end
21
+
22
+ def windows?
23
+ host.include?('mswin')
24
+ end
25
+
26
+ def linux?
27
+ host.include?('linux')
28
+ end
29
+
30
+ def applescript(script)
31
+ raise "Can't run AppleScript on #{host}" unless macos?
32
+ system "osascript -e '#{script}' 2>&1 >/dev/null"
33
+ end
34
+ end
35
+
36
+ class FirefoxBrowser < Browser
37
+ def initialize(path=File.join(ENV['ProgramFiles'] || 'c:\Program Files', '\Mozilla Firefox\firefox.exe'))
38
+ @path = path
39
+ end
40
+
41
+ def visit(url)
42
+ system("open -a Firefox '#{url}'") if macos?
43
+ system("#{@path} #{url}") if windows?
44
+ system("firefox #{url}") if linux?
45
+ end
46
+
47
+ def to_s
48
+ "Firefox"
49
+ end
50
+ end
51
+
52
+ class SafariBrowser < Browser
53
+ def supported?
54
+ macos?
55
+ end
56
+
57
+ def setup
58
+ applescript('tell application "Safari" to make new document')
59
+ end
60
+
61
+ def visit(url)
62
+ applescript('tell application "Safari" to set URL of front document to "' + url + '"')
63
+ end
64
+
65
+ def teardown
66
+ #applescript('tell application "Safari" to close front document')
67
+ end
68
+
69
+ def to_s
70
+ "Safari"
71
+ end
72
+ end
73
+
74
+ class IEBrowser < Browser
75
+ def setup
76
+ require 'win32ole' if windows?
77
+ end
78
+
79
+ def supported?
80
+ windows?
81
+ end
82
+
83
+ def visit(url)
84
+ if windows?
85
+ ie = WIN32OLE.new('InternetExplorer.Application')
86
+ ie.visible = true
87
+ ie.Navigate(url)
88
+ while ie.ReadyState != 4 do
89
+ sleep(1)
90
+ end
91
+ end
92
+ end
93
+
94
+ def to_s
95
+ "Internet Explorer"
96
+ end
97
+ end
98
+
99
+ class KonquerorBrowser < Browser
100
+ @@configDir = File.join((ENV['HOME'] || ''), '.kde', 'share', 'config')
101
+ @@globalConfig = File.join(@@configDir, 'kdeglobals')
102
+ @@konquerorConfig = File.join(@@configDir, 'konquerorrc')
103
+
104
+ def supported?
105
+ linux?
106
+ end
107
+
108
+ # Forces KDE's default browser to be Konqueror during the tests, and forces
109
+ # Konqueror to open external URL requests in new tabs instead of a new
110
+ # window.
111
+ def setup
112
+ cd @@configDir, :verbose => false do
113
+ copy @@globalConfig, "#{@@globalConfig}.bak", :preserve => true, :verbose => false
114
+ copy @@konquerorConfig, "#{@@konquerorConfig}.bak", :preserve => true, :verbose => false
115
+ # Too lazy to write it in Ruby... Is sed dependency so bad?
116
+ system "sed -ri /^BrowserApplication=/d '#{@@globalConfig}'"
117
+ system "sed -ri /^KonquerorTabforExternalURL=/s:false:true: '#{@@konquerorConfig}'"
118
+ end
119
+ end
120
+
121
+ def teardown
122
+ cd @@configDir, :verbose => false do
123
+ copy "#{@@globalConfig}.bak", @@globalConfig, :preserve => true, :verbose => false
124
+ copy "#{@@konquerorConfig}.bak", @@konquerorConfig, :preserve => true, :verbose => false
125
+ end
126
+ end
127
+
128
+ def visit(url)
129
+ system("kfmclient openURL #{url}")
130
+ end
131
+
132
+ def to_s
133
+ "Konqueror"
134
+ end
135
+ end
136
+
137
+ class OperaBrowser < Browser
138
+ def initialize(path='c:\Program Files\Opera\Opera.exe')
139
+ @path = path
140
+ end
141
+
142
+ def setup
143
+ if windows?
144
+ puts %{
145
+ MAJOR ANNOYANCE on Windows.
146
+ You have to shut down Opera manually after each test
147
+ for the script to proceed.
148
+ Any suggestions on fixing this is GREATLY appreciated!
149
+ Thank you for your understanding.
150
+ }
151
+ end
152
+ end
153
+
154
+ def visit(url)
155
+ applescript('tell application "Opera" to GetURL "' + url + '"') if macos?
156
+ system("#{@path} #{url}") if windows?
157
+ system("opera #{url}") if linux?
158
+ end
159
+
160
+ def to_s
161
+ "Opera"
162
+ end
163
+ end
164
+
165
+ # shut up, webrick :-)
166
+ class ::WEBrick::HTTPServer
167
+ def access_log(config, req, res)
168
+ # nop
169
+ end
170
+ end
171
+
172
+ class ::WEBrick::BasicLog
173
+ def log(level, data)
174
+ # nop
175
+ end
176
+ end
177
+
178
+ class WEBrick::HTTPResponse
179
+ alias send send_response
180
+ def send_response(socket)
181
+ send(socket) unless fail_silently?
182
+ end
183
+
184
+ def fail_silently?
185
+ @fail_silently
186
+ end
187
+
188
+ def fail_silently
189
+ @fail_silently = true
190
+ end
191
+ end
192
+
193
+ class WEBrick::HTTPRequest
194
+ def to_json
195
+ headers = []
196
+ each { |k, v| headers.push "#{k.inspect}: #{v.inspect}" }
197
+ headers = "{" << headers.join(', ') << "}"
198
+ %({ "headers": #{headers}, "body": #{body.inspect}, "method": #{request_method.inspect} })
199
+ end
200
+ end
201
+
202
+ class WEBrick::HTTPServlet::AbstractServlet
203
+ def prevent_caching(res)
204
+ res['ETag'] = nil
205
+ res['Last-Modified'] = Time.now + 100**4
206
+ res['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
207
+ res['Pragma'] = 'no-cache'
208
+ res['Expires'] = Time.now - 100**4
209
+ end
210
+ end
211
+
212
+ class BasicServlet < WEBrick::HTTPServlet::AbstractServlet
213
+ def do_GET(req, res)
214
+ prevent_caching(res)
215
+ res['Content-Type'] = "text/plain"
216
+
217
+ req.query.each do |k, v|
218
+ res[k] = v unless k == 'responseBody'
219
+ end
220
+ res.body = req.query["responseBody"]
221
+
222
+ raise WEBrick::HTTPStatus::OK
223
+ end
224
+
225
+ def do_POST(req, res)
226
+ do_GET(req, res)
227
+ end
228
+ end
229
+
230
+ class SlowServlet < BasicServlet
231
+ def do_GET(req, res)
232
+ sleep(2)
233
+ super
234
+ end
235
+ end
236
+
237
+ class DownServlet < BasicServlet
238
+ def do_GET(req, res)
239
+ res.fail_silently
240
+ end
241
+ end
242
+
243
+ class InspectionServlet < BasicServlet
244
+ def do_GET(req, res)
245
+ prevent_caching(res)
246
+ res['Content-Type'] = "application/json"
247
+ res.body = req.to_json
248
+ raise WEBrick::HTTPStatus::OK
249
+ end
250
+ end
251
+
252
+ class NonCachingFileHandler < WEBrick::HTTPServlet::FileHandler
253
+ def do_GET(req, res)
254
+ super
255
+ set_default_content_type(res, req.path)
256
+ prevent_caching(res)
257
+ end
258
+
259
+ def set_default_content_type(res, path)
260
+ res['Content-Type'] = case path
261
+ when /\.js$/ then 'text/javascript'
262
+ when /\.html$/ then 'text/html'
263
+ when /\.css$/ then 'text/css'
264
+ else 'text/plain'
265
+ end
266
+ end
267
+ end
268
+
269
+ class JavaScriptTestTask < ::Rake::TaskLib
270
+
271
+ def initialize(name=:test)
272
+ @name = name
273
+ @tests = []
274
+ @browsers = []
275
+
276
+ @queue = Queue.new
277
+
278
+ @server = WEBrick::HTTPServer.new(:Port => 4711) # TODO: make port configurable
279
+ @server.mount_proc("/results") do |req, res|
280
+ @queue.push({
281
+ :tests => req.query['tests'].to_i,
282
+ :assertions => req.query['assertions'].to_i,
283
+ :failures => req.query['failures'].to_i,
284
+ :errors => req.query['errors'].to_i
285
+ })
286
+ res.body = "OK"
287
+ end
288
+ @server.mount("/response", BasicServlet)
289
+ @server.mount("/slow", SlowServlet)
290
+ @server.mount("/down", DownServlet)
291
+ @server.mount("/inspect", InspectionServlet)
292
+ yield self if block_given?
293
+ define
294
+ end
295
+
296
+ def define
297
+ task @name do
298
+ trap("INT") { @server.shutdown }
299
+ t = Thread.new { @server.start }
300
+
301
+ # run all combinations of browsers and tests
302
+ @browsers.each do |browser|
303
+ if browser.supported?
304
+ t0 = Time.now
305
+ results = {:tests => 0, :assertions => 0, :failures => 0, :errors => 0}
306
+ errors = []
307
+ failures = []
308
+ browser.setup
309
+ puts "\nStarted tests in #{browser}"
310
+ @tests.each do |test|
311
+ params = "resultsURL=http://localhost:4711/results&t=" + ("%.6f" % Time.now.to_f)
312
+ if test.is_a?(Hash)
313
+ params << "&tests=#{test[:testcases]}" if test[:testcases]
314
+ test = test[:url]
315
+ end
316
+ browser.visit("http://localhost:4711#{test}?#{params}")
317
+
318
+ result = @queue.pop
319
+ result.each { |k, v| results[k] += v }
320
+ value = "."
321
+
322
+ if result[:failures] > 0
323
+ value = "F"
324
+ failures.push(test)
325
+ end
326
+
327
+ if result[:errors] > 0
328
+ value = "E"
329
+ errors.push(test)
330
+ end
331
+
332
+ print value
333
+ end
334
+
335
+ puts "\nFinished in #{(Time.now - t0).round.to_s} seconds."
336
+ puts " Failures: #{failures.join(', ')}" unless failures.empty?
337
+ puts " Errors: #{errors.join(', ')}" unless errors.empty?
338
+ puts "#{results[:tests]} tests, #{results[:assertions]} assertions, #{results[:failures]} failures, #{results[:errors]} errors"
339
+ browser.teardown
340
+ else
341
+ puts "\nSkipping #{browser}, not supported on this OS"
342
+ end
343
+ end
344
+
345
+ @server.shutdown
346
+ t.join
347
+ end
348
+ end
349
+
350
+ def mount(path, dir=nil)
351
+ dir = Dir.pwd + path unless dir
352
+
353
+ # don't cache anything in our tests
354
+ @server.mount(path, NonCachingFileHandler, dir)
355
+ end
356
+
357
+ # test should be specified as a url or as a hash of the form
358
+ # {:url => "url", :testcases => "testFoo,testBar"}
359
+ def run(test)
360
+ @tests<<test
361
+ end
362
+
363
+ def browser(browser)
364
+ browser =
365
+ case(browser)
366
+ when :firefox
367
+ FirefoxBrowser.new
368
+ when :safari
369
+ SafariBrowser.new
370
+ when :ie
371
+ IEBrowser.new
372
+ when :konqueror
373
+ KonquerorBrowser.new
374
+ when :opera
375
+ OperaBrowser.new
376
+ else
377
+ browser
378
+ end
379
+
380
+ @browsers<<browser
381
+ end
382
+ end