webr 0.0.5
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/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
|