newjs 1.0.0

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