webr 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -0
- data/Rakefile +19 -0
- data/app/webr.rb +57 -0
- data/bin/webr +6 -0
- data/ext/jasmine/lib/jasmine.js +2423 -0
- data/ext/jsdom/lib/jsdom.js +70 -0
- data/ext/jsdom/lib/jsdom/browser/domtohtml.js +198 -0
- data/ext/jsdom/lib/jsdom/browser/htmlencoding.js +381 -0
- data/ext/jsdom/lib/jsdom/browser/htmltodom.js +151 -0
- data/ext/jsdom/lib/jsdom/browser/index.js +484 -0
- data/ext/jsdom/lib/jsdom/level1/core.js +1610 -0
- data/ext/jsdom/lib/jsdom/level2/core.js +406 -0
- data/ext/jsdom/lib/jsdom/level2/events.js +358 -0
- data/ext/jsdom/lib/jsdom/level2/html.js +1424 -0
- data/ext/jsdom/lib/jsdom/level2/index.js +7 -0
- data/ext/jsdom/lib/jsdom/level2/languages/javascript.js +17 -0
- data/ext/jsdom/lib/jsdom/level3/core.js +514 -0
- data/ext/jsdom/lib/jsdom/level3/events.js +296 -0
- data/ext/jsdom/lib/jsdom/level3/html.js +5 -0
- data/ext/jsdom/lib/jsdom/level3/index.js +7 -0
- data/ext/node-htmlparser/lib/node-htmlparser.js +769 -0
- data/ext/node-htmlparser/lib/node-htmlparser.min.js +22 -0
- data/ext/request/request.js +116 -0
- data/js/jasmine-start.js +10 -0
- data/js/webr.js +97 -0
- data/jspec/jasmine_spec.js +23 -0
- data/lib/webr.rb +17 -0
- data/lib/webr/browser.rb +44 -0
- data/lib/webr/jasmine.rb +6 -0
- data/lib/webr/jasmine/browser.rb +15 -0
- data/lib/webr/jasmine/reporter.rb +16 -0
- data/lib/webr/jasmine/reporter/base.rb +40 -0
- data/lib/webr/jasmine/reporter/console.rb +79 -0
- data/lib/webr/jasmine/reporter/html.rb +179 -0
- data/lib/webr/portal.rb +19 -0
- data/lib/webr/runtime.rb +23 -0
- data/lib/webr/version.rb +3 -0
- data/spec/data/plain.html +13 -0
- data/spec/data/script-embedded.html +17 -0
- data/spec/data/script-external-onload.html +11 -0
- data/spec/data/script-external-onload.js +11 -0
- data/spec/data/script-external.html +11 -0
- data/spec/data/script-external.js +1 -0
- data/spec/data/script-jquery-1.4.2.html +12 -0
- data/spec/data/script-jquery-1.4.3.html +12 -0
- data/spec/data/script-jquery.js +3 -0
- data/spec/lib/webr/browser_spec.rb +133 -0
- data/spec/lib/webr/jasmine/browser_spec.rb +22 -0
- data/spec/lib/webr/jasmine/reporter/html_spec.rb +15 -0
- data/spec/spec_helper.rb +4 -0
- data/tasks/spec.rake +16 -0
- data/webr.gemspec +30 -0
- metadata +207 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
module Webr::Jasmine::Reporter
|
2
|
+
class Html < Webr::Jasmine::Reporter::Base
|
3
|
+
include ERB::Util # for h
|
4
|
+
|
5
|
+
def reportRunnerResults(runner)
|
6
|
+
super(runner)
|
7
|
+
puts summarize(runner)
|
8
|
+
end
|
9
|
+
|
10
|
+
def summarize(runner)
|
11
|
+
css = render_css
|
12
|
+
summary = render_summary(runner)
|
13
|
+
results = render_results(runner.topLevelSuites)
|
14
|
+
status = runner.results.failedCount > 0 ? 'failed' : 'passed'
|
15
|
+
"<!DOCTYPE html><html><head><title>Jasmine results</title>#{css}</head><body></body><div class='report'><div id='header' class='#{status}'><h1>Jasmine Code Examples</h1>#{summary}<div id='results' class='results'>#{results}</div></div></html>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_results(suites_or_specs)
|
19
|
+
html = []
|
20
|
+
suites_or_specs.each do |suite_or_spec|
|
21
|
+
html << render_suite(suite_or_spec) if @jasmine.isSuite(suite_or_spec)
|
22
|
+
html << render_spec(suite_or_spec) if @jasmine.isSpec(suite_or_spec)
|
23
|
+
end
|
24
|
+
html.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_suite(suite)
|
28
|
+
result = suite_passed(suite) ? 'passed' : 'failed'
|
29
|
+
content = render_results(suite.children)
|
30
|
+
"<div class='group #{result}'><div class='group-name'>#{h(suite.description)}</div>#{content}</div>"
|
31
|
+
end
|
32
|
+
|
33
|
+
def suite_passed(suite)
|
34
|
+
suite.results.getItems.each do |item|
|
35
|
+
return false unless item.passed
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_spec(spec)
|
41
|
+
result = spec.results.passed ? 'passed' : 'failed'
|
42
|
+
content = spec.results.passed ? '' : render_spec_failed(spec)
|
43
|
+
"<div class='example #{result}'><div class='example-name'>#{h(spec.description)}</div>#{content}</div>"
|
44
|
+
end
|
45
|
+
|
46
|
+
def render_spec_failed(spec)
|
47
|
+
html = []
|
48
|
+
name = spec.description
|
49
|
+
results = spec.results
|
50
|
+
results.getItems.each do |item|
|
51
|
+
unless item.passed
|
52
|
+
unless item.passed
|
53
|
+
backtrace = if error = item['error']
|
54
|
+
error.respond_to?(:stack) ? textmate_backtrace(h(filter_backtrace(error.stack))) : h(error)
|
55
|
+
else
|
56
|
+
textmate_backtrace h(filter_backtrace(item.trace.stack))
|
57
|
+
end
|
58
|
+
html << "<div class='example-failure'><div class='message'><pre>#{h(item.to_s)}</pre></div><div class='backtrace'><pre>#{backtrace}</pre></div></div>"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
html.join
|
63
|
+
end
|
64
|
+
|
65
|
+
def render_css
|
66
|
+
<<-EOCSS
|
67
|
+
<style>
|
68
|
+
html, body {
|
69
|
+
padding: 0;
|
70
|
+
margin: 0;
|
71
|
+
}
|
72
|
+
body {
|
73
|
+
font-size: 80%;
|
74
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
75
|
+
}
|
76
|
+
#header {
|
77
|
+
background: #000;
|
78
|
+
color: #fff;
|
79
|
+
height: 4em;
|
80
|
+
}
|
81
|
+
#header.passed {
|
82
|
+
background-color: #65C400;
|
83
|
+
}
|
84
|
+
#header.failed {
|
85
|
+
background-color: #c40d0d;
|
86
|
+
}
|
87
|
+
|
88
|
+
#header h1 {
|
89
|
+
font-size: 1.8em;
|
90
|
+
margin: 0 10px;
|
91
|
+
padding: 10px;
|
92
|
+
position: absolute;
|
93
|
+
}
|
94
|
+
|
95
|
+
.summary {
|
96
|
+
float: right;
|
97
|
+
margin: 0;
|
98
|
+
padding: 5px 10px;
|
99
|
+
right: 0;
|
100
|
+
top: 0;
|
101
|
+
}
|
102
|
+
.summary p {
|
103
|
+
margin: 0 0 0 2px;
|
104
|
+
}
|
105
|
+
.summary .totals {
|
106
|
+
font-size: 1.2em;
|
107
|
+
}
|
108
|
+
|
109
|
+
#results {
|
110
|
+
margin-bottom: 1em;
|
111
|
+
padding-right: 10px;
|
112
|
+
}
|
113
|
+
|
114
|
+
.group {
|
115
|
+
margin: 0 0 5px 10px;
|
116
|
+
padding: 0 0 5px;
|
117
|
+
font-size: 11px;
|
118
|
+
}
|
119
|
+
.group-name {
|
120
|
+
background-color: #000;
|
121
|
+
color: #fff;
|
122
|
+
font-weight: bold;
|
123
|
+
padding: 3px;
|
124
|
+
}
|
125
|
+
.group.failed .group-name {
|
126
|
+
background-color: #c40d0d;
|
127
|
+
}
|
128
|
+
.group.passed .group-name {
|
129
|
+
background-color: #65C400;
|
130
|
+
}
|
131
|
+
|
132
|
+
.example {
|
133
|
+
margin: 5px 0 5px 5px;
|
134
|
+
padding: 3px 3px 3px 18px;
|
135
|
+
}
|
136
|
+
.example.failed {
|
137
|
+
background-color: #fffbd3;
|
138
|
+
border-bottom: 1px solid #c40d0d;
|
139
|
+
border-left: 5px solid #c40d0d;
|
140
|
+
color: #C20000;
|
141
|
+
}
|
142
|
+
.example.passed {
|
143
|
+
background-color: #DBFFB4;
|
144
|
+
border-bottom: 1px solid #65C400;
|
145
|
+
border-left: 5px solid #65C400;
|
146
|
+
color: #3D7700;
|
147
|
+
}
|
148
|
+
.example .backtrace {
|
149
|
+
color: #000;
|
150
|
+
}
|
151
|
+
|
152
|
+
</style>
|
153
|
+
EOCSS
|
154
|
+
end
|
155
|
+
|
156
|
+
def render_summary(runner)
|
157
|
+
suites = runner.suites
|
158
|
+
specs = runner.specs
|
159
|
+
results = runner.results
|
160
|
+
|
161
|
+
hours, minutes, seconds, fraction = Date.day_fraction_to_time(@finished_at - @started_at)
|
162
|
+
time_taken = "%0.8f" % (hours*60*60 + minutes*60 + seconds + fraction.to_f)
|
163
|
+
|
164
|
+
totals = "Examples: #{specs.length}, Failure#{'s' unless results.failedCount == 1}: #{results.failedCount}"
|
165
|
+
duration = "Finished in #{time_taken}s"
|
166
|
+
"<div class='summary'><p class='totals'>#{totals}</p><p class='duration'>#{duration}</p></div></div>"
|
167
|
+
end
|
168
|
+
|
169
|
+
def textmate_backtrace(s)
|
170
|
+
lines = []
|
171
|
+
s.each_line do |line|
|
172
|
+
lines << line.gsub(/(\/.*\.js):(\d*)/) { "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a>" }
|
173
|
+
end
|
174
|
+
lines.join
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
data/lib/webr/portal.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Webr
|
2
|
+
class Portal
|
3
|
+
attr_accessor :scripts,
|
4
|
+
:html,
|
5
|
+
:root,
|
6
|
+
:require_paths,
|
7
|
+
:options,
|
8
|
+
:env
|
9
|
+
|
10
|
+
def initialize(node)
|
11
|
+
@node = node
|
12
|
+
@env = node.engine
|
13
|
+
@scripts = []
|
14
|
+
@require_paths = []
|
15
|
+
@options = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/webr/runtime.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rednode
|
2
|
+
class Process
|
3
|
+
attr_accessor :webr
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module Webr
|
8
|
+
class Runtime
|
9
|
+
attr_reader :node, :process, :portal
|
10
|
+
|
11
|
+
def initialize(script)
|
12
|
+
@node = Rednode::Node.new(script)
|
13
|
+
@process = Rednode::Process.new(@node)
|
14
|
+
|
15
|
+
@portal = Portal.new(@node)
|
16
|
+
@process.webr = @portal
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
@node.start(@process)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/webr/version.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>Script - Embedded</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1>Script - Changeme</h1>
|
9
|
+
<script>
|
10
|
+
// set global var
|
11
|
+
hello = 'world'
|
12
|
+
|
13
|
+
// change h1 to be title
|
14
|
+
document.getElementsByTagName('h1')[0].innerHTML = document.getElementsByTagName('title')[0].innerHTML
|
15
|
+
</script>
|
16
|
+
</body>
|
17
|
+
</html>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
window.onload = function() {
|
2
|
+
var div = document.createElement('div')
|
3
|
+
div.className = "onload"
|
4
|
+
document.body.appendChild(div)
|
5
|
+
}
|
6
|
+
|
7
|
+
window.addEventListener('load', function() {
|
8
|
+
var div = document.createElement('div')
|
9
|
+
div.className = "addEventListener"
|
10
|
+
document.body.appendChild(div)
|
11
|
+
})
|
@@ -0,0 +1 @@
|
|
1
|
+
document.getElementsByTagName('h1')[0].innerHTML = document.getElementsByTagName('title')[0].innerHTML
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>Script - jQuery</title>
|
6
|
+
<script src="../../ext/jquery/jquery-1.4.2.js"></script>
|
7
|
+
<script src="script-jquery.js"></script>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<h1>Script - Changeme</h1>
|
11
|
+
</body>
|
12
|
+
</html>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>Script - jQuery</title>
|
6
|
+
<script src="../../ext/jquery/jquery-1.4.3.js"></script>
|
7
|
+
<script src="script-jquery.js"></script>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<h1>Script - Changeme</h1>
|
11
|
+
</body>
|
12
|
+
</html>
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Webr::Browser do
|
4
|
+
|
5
|
+
it "instantiates" do
|
6
|
+
browser = Webr::Browser.new
|
7
|
+
end
|
8
|
+
|
9
|
+
context "in general" do
|
10
|
+
before(:all) do
|
11
|
+
@browser = Webr::Browser.new
|
12
|
+
@browser.start
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has loaded jsdom and thus has a dom" do
|
16
|
+
env = @browser.env
|
17
|
+
env['window'].should_not be_nil
|
18
|
+
env['window']['document'].should_not be_nil
|
19
|
+
document = env["document"].tap do |doc|
|
20
|
+
p = doc.createElement("p")
|
21
|
+
doc.body.appendChild(p)
|
22
|
+
ps = doc.getElementsByTagName("p")
|
23
|
+
ps.length.should == 1
|
24
|
+
p.parentNode.removeChild(p)
|
25
|
+
ps.length.should == 0 # live list
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "has loaded node-htmlparser and thus can set innerHTML" do
|
30
|
+
env = @browser.env
|
31
|
+
env["document"].tap do |doc|
|
32
|
+
div = doc.createElement('div')
|
33
|
+
doc.body.appendChild(div)
|
34
|
+
div.innerHTML = '<p>Test</p>'
|
35
|
+
doc.getElementsByTagName('p')[0].innerHTML.should == "Test"
|
36
|
+
div.parentNode.removeChild(div)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "bases script load paths off of 'root'"
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "loading webpages" do
|
45
|
+
before(:each) do
|
46
|
+
@browser = Webr::Browser.new
|
47
|
+
end
|
48
|
+
|
49
|
+
it "loads a web page from a file" do
|
50
|
+
@browser.open("#{DATA_PATH}/plain.html")
|
51
|
+
@browser.start
|
52
|
+
@browser.env["document"].tap do |doc|
|
53
|
+
doc.getElementsByTagName('meta').tap do |meta|
|
54
|
+
meta.length.should == 1
|
55
|
+
meta[0].getAttribute('charset').should == "utf-8"
|
56
|
+
end
|
57
|
+
doc.getElementsByTagName('title').tap do |title|
|
58
|
+
title.length.should == 1
|
59
|
+
title[0].innerHTML.should == "Plain HTML"
|
60
|
+
end
|
61
|
+
doc.getElementsByTagName('h1').tap do |h1|
|
62
|
+
h1.length.should == 1
|
63
|
+
h1[0].innerHTML.should == "Plain"
|
64
|
+
end
|
65
|
+
doc.getElementsByTagName('p').tap do |p|
|
66
|
+
p.length.should == 3
|
67
|
+
p[0].innerHTML.should == "Foo"
|
68
|
+
p[1].innerHTML.should == "Bar"
|
69
|
+
p[2].innerHTML.should == "Baz"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "loads a webpage containing embedded javascript from a file and executes the javascript" do
|
75
|
+
@browser.open("#{DATA_PATH}/script-embedded.html")
|
76
|
+
@browser.start
|
77
|
+
@browser.env["hello"].should == "world"
|
78
|
+
@browser.env["document"].tap do |document|
|
79
|
+
h1 = document.getElementsByTagName('h1')[0]
|
80
|
+
title = document.getElementsByTagName('title')[0]
|
81
|
+
h1.innerHTML.should == title.innerHTML
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "loads a webpage containing external javascript from a file and executes the javascript" do
|
86
|
+
@browser.open("#{DATA_PATH}/script-external.html")
|
87
|
+
@browser.start
|
88
|
+
@browser.env["document"].tap do |document|
|
89
|
+
h1 = document.getElementsByTagName('h1')[0]
|
90
|
+
title = document.getElementsByTagName('title')[0]
|
91
|
+
h1.innerHTML.should == title.innerHTML
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "triggers the window load events" do
|
96
|
+
@browser.open("#{DATA_PATH}/script-external-onload.html")
|
97
|
+
@browser.start
|
98
|
+
@browser.env["document"].tap do |document|
|
99
|
+
document.getElementsByClassName('onload').length.should == 1
|
100
|
+
document.getElementsByClassName('addEventListener').length.should == 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "loads and executes the jasmine test suite" do
|
105
|
+
pending "this actually works but takes over 10 seconds. Need to figure out why it's so slow."
|
106
|
+
@browser.open("#{EXT_PATH}/jasmine/spec/runner.html")
|
107
|
+
@browser.start
|
108
|
+
@browser.env["jasmine"].should_not be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "loads a webpage containing jQuery 1.4.2 from a file and executes the javascript" do
|
112
|
+
@browser.open("#{DATA_PATH}/script-jquery-1.4.2.html")
|
113
|
+
@browser.start
|
114
|
+
@browser.env["document"].tap do |document|
|
115
|
+
h1 = document.getElementsByTagName('h1')[0]
|
116
|
+
title = document.getElementsByTagName('title')[0]
|
117
|
+
h1.innerHTML.should == title.innerHTML
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "loads a webpage containing jQuery 1.4.3 from a file and executes the javascript" do
|
122
|
+
@browser.open("#{DATA_PATH}/script-jquery-1.4.3.html")
|
123
|
+
@browser.start
|
124
|
+
@browser.env["document"].tap do |document|
|
125
|
+
h1 = document.getElementsByTagName('h1')[0]
|
126
|
+
title = document.getElementsByTagName('title')[0]
|
127
|
+
h1.innerHTML.should == title.innerHTML
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|