jasmine_webos 0.0.6

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.
@@ -0,0 +1,57 @@
1
+ require 'optparse'
2
+ require 'fileutils'
3
+
4
+ module Jasminewebos
5
+ class CLI
6
+ def self.execute(stdout, arguments=[])
7
+ command = ""
8
+ mandatory_options = %w( )
9
+
10
+ generate = false
11
+ start_server = false
12
+
13
+ parser = OptionParser.new do |opts|
14
+ opts.banner = <<-BANNER.gsub(/^ /,'')
15
+ Tools for working with jasmine_webos
16
+
17
+ Usage:
18
+ #{File.basename($0)} -g
19
+ generates the jasmine files in the current directory
20
+
21
+ #{File.basename($0)} -s
22
+ starts the jasmine server from the current directory
23
+
24
+ Options:
25
+ BANNER
26
+ opts.separator ""
27
+ opts.on("-g", String,
28
+ "Starts the jasmine server from the current directory") { generate = true }
29
+ opts.on("-s", String,
30
+ "Generate the jasmine files in the current directory") { start_server = true }
31
+ opts.on("-h", "--help",
32
+ "Show this help message.") { stdout.puts opts; exit }
33
+ opts.parse!(arguments)
34
+
35
+ if mandatory_options && mandatory_options.find { |option| options[option.to_sym].nil? }
36
+ stdout.puts opts; exit
37
+ end
38
+ end
39
+
40
+ config = Jasminewebos::Configuration.new(FileUtils.pwd)
41
+
42
+ self.generate_stub(config) if generate
43
+ self.launch_server(config) if start_server
44
+
45
+ end
46
+
47
+ def self.generate_stub(config)
48
+ puts("Generating jasmine_webos required files")
49
+ Jasminewebos::Generator.new(config).run
50
+ puts(" Complete.")
51
+ end
52
+
53
+ def self.launch_server(config)
54
+ Jasminewebos::Server.new(config).start
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,16 @@
1
+ module Jasminewebos
2
+ class Configuration
3
+ attr_accessor :port, :jasmine_root, :application_root, :specs_dir,
4
+ :matchers_dir, :sources_json, :jasminewebos_root
5
+
6
+ def initialize(application_root)
7
+ @port = 8888
8
+ @jasminewebos_root = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
9
+ @jasmine_root = File.join(@jasminewebos_root, "vendor", "jasmine")
10
+ @application_root = application_root
11
+ @specs_dir = File.join(@application_root, "spec", "javascript", "spec")
12
+ @matchers_dir = File.join(@application_root, "spec", "javascript", "matchers")
13
+ @sources_json = File.join(@application_root, "sources.json")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ require 'fileutils'
2
+ module Jasminewebos
3
+ class Generator
4
+ def initialize(config)
5
+ @config = config
6
+ end
7
+ def run
8
+ from = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "templates", "webos", "spec"))
9
+ FileUtils.cp_r(from,
10
+ @config.application_root)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,76 @@
1
+ module Jasminewebos
2
+ class Server
3
+ def initialize(configuration)
4
+ @configuration = configuration
5
+ end
6
+
7
+ def start
8
+ puts "Starting JasmineWebOS Server from #{@configuration.application_root}"
9
+ puts "on http://localhost:#{@configuration.port}"
10
+
11
+ require File.expand_path(File.join(@configuration.jasmine_root,
12
+ "contrib",
13
+ "ruby",
14
+ "jasmine_spec_builder"))
15
+
16
+
17
+ Jasmine::SimpleServer.start(@configuration.port,
18
+ lambda{spec_files},
19
+ dir_mappings,
20
+ lambda{source_files})
21
+ end
22
+
23
+ def spec_files
24
+ raw_specs = Dir.glob(File.join(@configuration.specs_dir, "**/*[Ss]pec.js"))
25
+ raw_specs.collect {|f| f.sub(@configuration.specs_dir, "/spec")}
26
+ end
27
+
28
+ def source_files
29
+ jasmine = Dir.glob(File.join(jasmine_lib_dir, "*"))
30
+ jasmine = jasmine.collect {|f| f.sub(jasmine_lib_dir, "/lib")}
31
+
32
+ matchers = Dir.glob(File.join(@configuration.matchers_dir, "**/*.js"))
33
+ matchers = matchers.collect {|f| f.sub(@configuration.matchers_dir, "/matchers")}
34
+
35
+ sources = Dir.glob(File.join(application_src_dir, "**/*.js"))
36
+ sources = sources.collect {|f| f.sub(application_src_dir, "/app")}
37
+
38
+ javascripts_sources = Dir.glob(File.join(javascripts_sources_dir, "**/*.js"))
39
+ javascripts_sources = javascripts_sources.collect {|f| f.sub(javascripts_sources_dir, "/javascripts")}
40
+
41
+ framework = Dir.glob(File.join(framework_dir, "**/*.js"))
42
+ framework = framework.collect {|f| f.sub(framework_dir, "/framework")}
43
+
44
+ framework + jasmine.sort.reverse + matchers.sort + sources.sort + javascripts_sources.sort
45
+ end
46
+
47
+ def dir_mappings
48
+ {
49
+ "/framework" => framework_dir,
50
+ "/app" => application_src_dir,
51
+ "/spec" => @configuration.specs_dir,
52
+ "/matchers" => @configuration.matchers_dir,
53
+ "/lib" => jasmine_lib_dir,
54
+ "/matchers" => @configuration.matchers_dir,
55
+ "/javascripts" => javascripts_sources_dir
56
+ }
57
+ end
58
+
59
+ private
60
+ def javascripts_sources_dir
61
+ File.join(@configuration.application_root, "javascripts")
62
+ end
63
+
64
+ def framework_dir
65
+ File.join(@configuration.jasminewebos_root, "jslib")
66
+ end
67
+
68
+ def application_src_dir
69
+ File.join(@configuration.application_root, "app")
70
+ end
71
+
72
+ def jasmine_lib_dir
73
+ File.expand_path(File.join(@configuration.jasmine_root, "lib"))
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Jasminewebos
5
+ VERSION = '0.0.6'
6
+
7
+ # def configure(&block)
8
+ # @@configuration = Jasminewebos::Configuration.new
9
+ # yield @@configuration
10
+ # end
11
+ #
12
+ # def configuration
13
+ # @@configuration
14
+ # end
15
+ end
16
+
17
+ require "jasminewebos/cli"
18
+ require "jasminewebos/server"
19
+ require "jasminewebos/generator"
20
+ require "jasminewebos/configuration"
@@ -0,0 +1,12 @@
1
+ /**
2
+ * This file contains matchers that are for all tests
3
+ */
4
+ /**
5
+ * Matcher that expects to be undefined
6
+ */
7
+ jasmine.Matchers.prototype.toBeUndefined = function() {
8
+ return this.report((this.actual === undefined),
9
+ 'Expected a value to be undefined but it was defined (' + this.report + ').');
10
+ };
11
+ /** @deprecated */
12
+ jasmine.Matchers.prototype.should_be_defined = jasmine.Matchers.prototype.toBeDefined;
@@ -0,0 +1,5 @@
1
+ describe("sample", function(){
2
+ it("should allow true to be true", function(){
3
+ expect(true).toEqual(true);
4
+ });
5
+ });
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/../test_helper.rb'
2
+
3
+ class Jasminewebos::TestConfiguration < Test::Unit::TestCase
4
+
5
+ context "with a default config" do
6
+ setup do
7
+ @config = Jasminewebos::Configuration.new(File.dirname(__FILE__))
8
+ end
9
+ should "have default port" do
10
+ assert_equal(8888, @config.port)
11
+ end
12
+ should "have jasmine_root" do
13
+ assert_equal(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "vendor", "jasmine")),
14
+ @config.jasmine_root)
15
+ end
16
+ should "have an app root" do
17
+ assert_equal(File.dirname(__FILE__), @config.application_root)
18
+ end
19
+
20
+ should "have sources.json" do
21
+ assert_equal(File.join(File.dirname(__FILE__), "sources.json"), @config.sources_json)
22
+ end
23
+
24
+ should "have specs_dir" do
25
+ assert_equal(File.join(File.dirname(__FILE__), "spec", "javascript", "spec"), @config.specs_dir)
26
+ end
27
+
28
+ should "have matchers_dir" do
29
+ assert_equal(File.join(File.dirname(__FILE__), "spec", "javascript", "matchers"), @config.matchers_dir)
30
+ end
31
+
32
+ should "have jasminewebos_root" do
33
+ assert_equal(File.expand_path(File.join(File.dirname(__FILE__), "..", "..")),
34
+ @config.jasminewebos_root)
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), "/../test_helper.rb")
2
+ require 'jasminewebos/cli'
3
+
4
+ class TestJasminewebosCli < Test::Unit::TestCase
5
+ # def setup
6
+ # Jasminewebos::CLI.execute(@stdout_io = StringIO.new, [])
7
+ # @stdout_io.rewind
8
+ # @stdout = @stdout_io.read
9
+ # end
10
+ #
11
+ # def test_print_default_output
12
+ # assert_match(/To update this executable/, @stdout)
13
+ # end
14
+
15
+ def test_true
16
+
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../test_helper.rb'
2
+
3
+ class Jasminewebos::TestServer < Test::Unit::TestCase
4
+ def test_monkeys
5
+
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require File.dirname(__FILE__) + '/../lib/jasminewebos'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestJasminewebos < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,246 @@
1
+ require 'socket'
2
+ require 'erb'
3
+ require 'json'
4
+
5
+ module Jasmine
6
+ def self.root
7
+ File.expand_path(File.join(File.dirname(__FILE__), '../..'))
8
+ end
9
+
10
+ # this seemingly-over-complex method is necessary to get an open port on at least some of our Macs
11
+ def self.open_socket_on_unused_port
12
+ infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
13
+ families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
14
+
15
+ return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET')
16
+ return TCPServer.open('::', 0) if families.has_key?('AF_INET6')
17
+ return TCPServer.open(0)
18
+ end
19
+
20
+ def self.find_unused_port
21
+ socket = open_socket_on_unused_port
22
+ port = socket.addr[1]
23
+ socket.close
24
+ port
25
+ end
26
+
27
+ def self.server_is_listening_on(hostname, port)
28
+ require 'socket'
29
+ begin
30
+ socket = TCPSocket.open(hostname, port)
31
+ rescue Errno::ECONNREFUSED
32
+ return false
33
+ end
34
+ socket.close
35
+ true
36
+ end
37
+
38
+ def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10)
39
+ time_out_at = Time.now + seconds_to_wait
40
+ until server_is_listening_on "localhost", port
41
+ sleep 0.1
42
+ puts "Waiting for #{name} on #{port}..."
43
+ raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at
44
+ end
45
+ end
46
+
47
+ def self.kill_process_group(process_group_id, signal="TERM")
48
+ Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
49
+ end
50
+
51
+ def self.cachebust(files, root_dir="", replace=nil, replace_with=nil)
52
+ files.collect do |file_name|
53
+ real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name
54
+ begin
55
+ digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}"))
56
+ rescue
57
+ digest = "MISSING-FILE"
58
+ end
59
+ "#{file_name}?cachebust=#{digest}"
60
+ end
61
+ end
62
+
63
+ class RunAdapter
64
+ def initialize(spec_files_or_proc, jasmine_files = nil)
65
+ @spec_files_or_proc = spec_files_or_proc
66
+ @jasmine_files = jasmine_files || [
67
+ "/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first),
68
+ "/__JASMINE_ROOT__/lib/TrivialReporter.js",
69
+ "/__JASMINE_ROOT__/lib/json2.js"
70
+ ]
71
+ end
72
+
73
+ def call(env)
74
+ spec_files = @spec_files_or_proc
75
+ spec_files = spec_files.call if spec_files.respond_to?(:call)
76
+
77
+ jasmine_files = @jasmine_files
78
+ jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call)
79
+
80
+ css_files = ["/__JASMINE_ROOT__/lib/jasmine.css"]
81
+
82
+ body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding)
83
+ [
84
+ 200,
85
+ { 'Content-Type' => 'text/html' },
86
+ body
87
+ ]
88
+ end
89
+ end
90
+
91
+ class Redirect
92
+ def initialize(url)
93
+ @url = url
94
+ end
95
+
96
+ def call(env)
97
+ [
98
+ 302,
99
+ { 'Location' => @url },
100
+ []
101
+ ]
102
+ end
103
+ end
104
+
105
+ class JsAlert
106
+ def call(env)
107
+ [
108
+ 200,
109
+ { 'Content-Type' => 'application/javascript' },
110
+ "document.write('<p>Couldn\\'t load #{env["PATH_INFO"]}!</p>');"
111
+ ]
112
+ end
113
+ end
114
+
115
+ class SimpleServer
116
+ def self.start(port, spec_files_or_proc, mappings, jasmine_files = nil)
117
+ require 'thin'
118
+
119
+ config = {
120
+ '/run.html' => Jasmine::Redirect.new('/'),
121
+ '/' => Jasmine::RunAdapter.new(spec_files_or_proc, jasmine_files)
122
+ }
123
+ mappings.each do |from, to|
124
+ config[from] = Rack::File.new(to)
125
+ end
126
+
127
+ config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
128
+
129
+ app = Rack::Cascade.new([
130
+ Rack::URLMap.new(config),
131
+ JsAlert.new
132
+ ])
133
+
134
+ Thin::Server.start('0.0.0.0', port, app)
135
+ end
136
+ end
137
+
138
+ class SimpleClient
139
+ def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
140
+ require 'selenium/client'
141
+ @driver = Selenium::Client::Driver.new(
142
+ selenium_host,
143
+ selenium_port,
144
+ selenium_browser_start_command,
145
+ http_address
146
+ )
147
+ @http_address = http_address
148
+ end
149
+
150
+ def tests_have_finished?
151
+ @driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
152
+ end
153
+
154
+ def connect
155
+ @driver.start
156
+ @driver.open("/")
157
+ end
158
+
159
+ def disconnect
160
+ @driver.stop
161
+ end
162
+
163
+ def run
164
+ until tests_have_finished? do
165
+ sleep 0.1
166
+ end
167
+
168
+ puts @driver.get_eval("window.results()")
169
+ failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
170
+ failed_count == 0
171
+ end
172
+
173
+ def eval_js(script)
174
+ escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
175
+
176
+ result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
177
+ JSON.parse("[#{result}]")[0]
178
+ end
179
+ end
180
+
181
+ class Runner
182
+ def initialize(selenium_jar_path, spec_files, dir_mappings, jasmine_files = nil, options={})
183
+ @selenium_jar_path = selenium_jar_path
184
+ @spec_files = spec_files
185
+ @dir_mappings = dir_mappings
186
+ @jasmine_files = jasmine_files
187
+ @browser = options[:browser] || 'firefox'
188
+
189
+ @selenium_pid = nil
190
+ @jasmine_server_pid = nil
191
+ end
192
+
193
+ def start
194
+ start_servers
195
+ @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
196
+ @client.connect
197
+ end
198
+
199
+ def stop
200
+ @client.disconnect
201
+ stop_servers
202
+ end
203
+
204
+ def start_servers
205
+ @jasmine_server_port = Jasmine::find_unused_port
206
+ @selenium_server_port = Jasmine::find_unused_port
207
+
208
+ @selenium_pid = fork do
209
+ Process.setpgrp
210
+ exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
211
+ end
212
+ puts "selenium started. pid is #{@selenium_pid}"
213
+
214
+ @jasmine_server_pid = fork do
215
+ Process.setpgrp
216
+ Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @dir_mappings, @jasmine_files)
217
+ exit! 0
218
+ end
219
+ puts "jasmine server started. pid is #{@jasmine_server_pid}"
220
+
221
+ Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
222
+ Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
223
+ end
224
+
225
+ def stop_servers
226
+ puts "shutting down the servers..."
227
+ Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
228
+ Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
229
+ end
230
+
231
+ def run
232
+ begin
233
+ start
234
+ puts "servers are listening on their ports -- running the test script..."
235
+ tests_passed = @client.run
236
+ ensure
237
+ stop
238
+ end
239
+ return tests_passed
240
+ end
241
+
242
+ def eval_js(script)
243
+ @client.eval_js(script)
244
+ end
245
+ end
246
+ end