newjs 1.2.1 → 1.3.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.
- data/History.txt +2 -1
- data/Manifest.txt +9 -0
- data/javascript_test_generators/functional_test/functional_test_generator.rb +1 -2
- data/javascript_test_generators/unit_test/unit_test_generator.rb +1 -1
- data/lib/newjs/version.rb +2 -2
- data/rails_generators/javascript_test/USAGE +5 -0
- data/rails_generators/javascript_test/javascript_test_generator.rb +65 -0
- data/rails_generators/javascript_test/templates/assets/jsunittest.js +964 -0
- data/rails_generators/javascript_test/templates/assets/unittest.css +50 -0
- data/rails_generators/javascript_test/templates/plugins/javascript_unittest/README +10 -0
- data/rails_generators/javascript_test/templates/plugins/javascript_unittest/lib/jstest.rb +382 -0
- data/rails_generators/javascript_test/templates/plugins/javascript_unittest/tasks/runner.rake +24 -0
- data/rails_generators/javascript_test/templates/test.html.erb +57 -0
- data/test/test_functional_test_generator.rb +1 -1
- data/test/test_javascript_test_generator.rb +60 -0
- data/website/index.html +1 -1
- metadata +12 -2
@@ -0,0 +1,50 @@
|
|
1
|
+
body, div, p, h1, h2, h3, ul, ol, span, a, table, td, form, img, li {
|
2
|
+
font-family: sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
body {
|
6
|
+
font-size:0.8em;
|
7
|
+
}
|
8
|
+
|
9
|
+
#log {
|
10
|
+
padding-bottom: 1em;
|
11
|
+
border-bottom: 2px solid #000;
|
12
|
+
margin-bottom: 2em;
|
13
|
+
}
|
14
|
+
|
15
|
+
.logsummary {
|
16
|
+
margin-top: 1em;
|
17
|
+
margin-bottom: 1em;
|
18
|
+
padding: 1ex;
|
19
|
+
border: 1px solid #000;
|
20
|
+
font-weight: bold;
|
21
|
+
}
|
22
|
+
|
23
|
+
.logtable {
|
24
|
+
width:100%;
|
25
|
+
border-collapse: collapse;
|
26
|
+
border: 1px dotted #666;
|
27
|
+
}
|
28
|
+
|
29
|
+
.logtable td, .logtable th {
|
30
|
+
text-align: left;
|
31
|
+
padding: 3px 8px;
|
32
|
+
border: 1px dotted #666;
|
33
|
+
}
|
34
|
+
|
35
|
+
.logtable .passed {
|
36
|
+
background-color: #cfc;
|
37
|
+
}
|
38
|
+
|
39
|
+
.logtable .failed, .logtable .error {
|
40
|
+
background-color: #fcc;
|
41
|
+
}
|
42
|
+
|
43
|
+
.logtable td div.action_buttons {
|
44
|
+
display: inline;
|
45
|
+
}
|
46
|
+
|
47
|
+
.logtable td div.action_buttons input {
|
48
|
+
margin: 0 5px;
|
49
|
+
font-size: 10px;
|
50
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
javascript_unittest plugin
|
2
|
+
|
3
|
+
This plugin was installed by newjs' javascript_test generator for Rails 2.0+ applications.
|
4
|
+
|
5
|
+
Its purpose is to provide the 'rake test:javascripts' test runner.
|
6
|
+
|
7
|
+
See http://newjs.rubyforge.org for more details.
|
8
|
+
|
9
|
+
Author:
|
10
|
+
Dr Nic Williams, drnicwilliams@gmail.com
|
@@ -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, port=4711)
|
272
|
+
@name = name
|
273
|
+
@tests = []
|
274
|
+
@browsers = []
|
275
|
+
@port = port
|
276
|
+
@queue = Queue.new
|
277
|
+
|
278
|
+
@server = WEBrick::HTTPServer.new(:Port => @port) # 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:#{@port}/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:#{@port}#{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
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/jstest'
|
2
|
+
|
3
|
+
namespace :test do
|
4
|
+
desc "Runs all the JavaScript unit tests and collects the results"
|
5
|
+
JavaScriptTestTask.new(:javascripts, 4711) do |t|
|
6
|
+
testcases = ENV['TESTCASES']
|
7
|
+
tests_to_run = ENV['TESTS'] && ENV['TESTS'].split(',')
|
8
|
+
browsers_to_test = ENV['BROWSERS'] && ENV['BROWSERS'].split(',')
|
9
|
+
|
10
|
+
t.mount("/dist")
|
11
|
+
t.mount("/src")
|
12
|
+
t.mount("/test")
|
13
|
+
|
14
|
+
Dir["test/javascript/*_test.html"].sort.each do |test_file|
|
15
|
+
tests = testcases ? { :url => "/#{test_file}", :testcases => testcases } : "/#{test_file}"
|
16
|
+
test_filename = test_file[/.*\/(.+?)\.html/, 1]
|
17
|
+
t.run(tests) unless tests_to_run && !tests_to_run.include?(test_filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
%w( safari firefox ie konqueror opera ).each do |browser|
|
21
|
+
t.browser(browser.to_sym) unless browsers_to_test && !browsers_to_test.include?(browser)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|