js_spec 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +3 -0
- data/Rakefile +3 -2
- data/vendor/js-test-core/CHANGES +15 -0
- data/vendor/js-test-core/README +12 -0
- data/vendor/js-test-core/Rakefile +72 -0
- data/vendor/js-test-core/lib/js_test_core.rb +38 -0
- data/vendor/js-test-core/lib/js_test_core/client.rb +114 -0
- data/vendor/js-test-core/lib/js_test_core/extensions.rb +3 -0
- data/vendor/js-test-core/lib/js_test_core/extensions/time.rb +6 -0
- data/vendor/js-test-core/lib/js_test_core/rack.rb +2 -0
- data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +5 -0
- data/vendor/js-test-core/lib/js_test_core/rails_server.rb +22 -0
- data/vendor/js-test-core/lib/js_test_core/resources.rb +10 -0
- data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +67 -0
- data/vendor/js-test-core/lib/js_test_core/resources/file.rb +40 -0
- data/vendor/js-test-core/lib/js_test_core/resources/file_not_found.rb +11 -0
- data/vendor/js-test-core/lib/js_test_core/resources/runner.rb +105 -0
- data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +46 -0
- data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +17 -0
- data/vendor/js-test-core/lib/js_test_core/resources/suite.rb +40 -0
- data/vendor/js-test-core/lib/js_test_core/resources/suite_finish.rb +17 -0
- data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +63 -0
- data/vendor/js-test-core/lib/js_test_core/selenium.rb +2 -0
- data/vendor/js-test-core/lib/js_test_core/selenium/selenium_driver.rb +5 -0
- data/vendor/js-test-core/lib/js_test_core/selenium_server_configuration.rb +48 -0
- data/vendor/js-test-core/lib/js_test_core/server.rb +50 -0
- data/vendor/js-test-core/lib/js_test_core/thin.rb +3 -0
- data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
- data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +8 -0
- data/vendor/js-test-core/spec/example_core/JsTestCore.css +0 -0
- data/vendor/js-test-core/spec/example_core/JsTestCore.js +0 -0
- data/vendor/js-test-core/spec/example_public/favicon.ico +0 -0
- data/vendor/js-test-core/spec/example_public/javascripts/foo.js +3 -0
- data/vendor/js-test-core/spec/example_public/javascripts/large_file.js +59 -0
- data/vendor/js-test-core/spec/example_public/javascripts/subdir/bar.js +1 -0
- data/vendor/js-test-core/spec/example_public/robots.txt +0 -0
- data/vendor/js-test-core/spec/example_public/stylesheets/example.css +3 -0
- data/vendor/js-test-core/spec/example_specs/failing_spec.js +5 -0
- data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +6 -0
- data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +6 -0
- data/vendor/js-test-core/spec/spec_suite.rb +2 -0
- data/vendor/js-test-core/spec/specs/failing_spec.js +0 -0
- data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +166 -0
- data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +45 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +52 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +16 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +90 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/runner_spec.rb +283 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +105 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +42 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_finish_spec.rb +82 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_spec.rb +86 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +32 -0
- data/vendor/js-test-core/spec/unit/js_test_core/selenium_server_configuration_spec.rb +49 -0
- data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +117 -0
- data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +6 -0
- data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +134 -0
- data/vendor/js-test-core/spec/unit_suite.rb +10 -0
- data/vendor/js-test-core/vendor/thin-rest/CHANGES +2 -0
- data/vendor/js-test-core/vendor/thin-rest/README +0 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest.rb +9 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/connection.rb +116 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions.rb +3 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions/object.rb +21 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resource.rb +104 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resource_invalid.rb +4 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/routing_error.rb +5 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/spec_suite.rb +5 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/connection_spec.rb +207 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resource_spec.rb +127 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest_spec_helper.rb +124 -0
- metadata +120 -17
data/CHANGES
CHANGED
data/Rakefile
CHANGED
@@ -26,14 +26,15 @@ def run_suite
|
|
26
26
|
end
|
27
27
|
|
28
28
|
PKG_NAME = "js_spec"
|
29
|
-
PKG_VERSION = "0.3.
|
29
|
+
PKG_VERSION = "0.3.2"
|
30
30
|
PKG_FILES = FileList[
|
31
31
|
'[A-Z]*',
|
32
32
|
'*.rb',
|
33
33
|
'lib/**/*.rb',
|
34
34
|
'core/**',
|
35
35
|
'bin/**',
|
36
|
-
'spec/**/*.rb'
|
36
|
+
'spec/**/*.rb',
|
37
|
+
'vendor/**/*'
|
37
38
|
]
|
38
39
|
|
39
40
|
spec = Gem::Specification.new do |s|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
- Remove File caching because it doesn't cause a noticable performance benefit over a local network and because it sometimes doesn't write over stale files.
|
2
|
+
- Client accepts selenium_browser_start_command parameter, which allows the user to parameterize the selenium_browser_start_command
|
3
|
+
- Added support for running specs in Internet Explorer via POST /runners/iexplore
|
4
|
+
- Resource file download performance improvements via caching and chunked sending
|
5
|
+
- Fixed false positive bug when Client connection times out
|
6
|
+
|
7
|
+
0.1.1
|
8
|
+
- SuiteFinish#post immediately closes the connection
|
9
|
+
|
10
|
+
0.1.0
|
11
|
+
- Initial Release extracted from JsTestCore.
|
12
|
+
- Added JsTestCore::WebRoot.dispatch_specs and .dispatch_strategy
|
13
|
+
- Extracted JsTestCore::Resources::Specs::SpecDir
|
14
|
+
- Extracted JsTestCore::Resources::Specs::SpecFile
|
15
|
+
- No longer depending on Guid. The child libraries are responsible for obtaining the Selenium session_id from the client by using top.runOptions.getSessionId().
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= JsTestCore
|
2
|
+
The JsTestCore library is the core javascript test server library used by several JS Test server libraries.
|
3
|
+
|
4
|
+
To hook up your own JS Test framework:
|
5
|
+
* You will need to call either JsTestCore::Resources::WebRoot.dispatch_specs or JsTestCore::Resources::WebRoot.dispatch_tests
|
6
|
+
depending if you are serving specs or tests.
|
7
|
+
* Set JsTestCore.core_path to the directory of the client side test framework (javascript files)
|
8
|
+
* Override JsTestCore::Resources::Specs::SpecFile#get or JsTestCore::Resources::Specs::TestFile#get
|
9
|
+
* Override JsTestCore::Resources::Specs::SpecDir#get or JsTestCore::Resources::Specs::TestDir#get
|
10
|
+
|
11
|
+
NOTE: The current version of JsTestCore does not yet support tests. Support will be added soon.
|
12
|
+
I just wanted the test stuff to be in the docs to establish the current architectural direction.
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "rake"
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/contrib/rubyforgepublisher'
|
4
|
+
require 'rake/clean'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
|
8
|
+
desc "Runs the Rspec suite"
|
9
|
+
task(:default) do
|
10
|
+
run_suite
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Runs the Rspec suite"
|
14
|
+
task(:spec) do
|
15
|
+
run_suite
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Copies the trunk to a tag with the name of the current release"
|
19
|
+
task(:tag_release) do
|
20
|
+
tag_release
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_suite
|
24
|
+
dir = File.dirname(__FILE__)
|
25
|
+
system("ruby #{dir}/spec/spec_suite.rb") || raise("Example Suite failed")
|
26
|
+
end
|
27
|
+
|
28
|
+
PKG_NAME = "js_test_core"
|
29
|
+
PKG_VERSION = "0.1.1"
|
30
|
+
PKG_FILES = FileList[
|
31
|
+
'[A-Z]*',
|
32
|
+
'*.rb',
|
33
|
+
'lib/**/*.rb',
|
34
|
+
'core/**',
|
35
|
+
'bin/**',
|
36
|
+
'spec/**/*.rb'
|
37
|
+
]
|
38
|
+
|
39
|
+
spec = Gem::Specification.new do |s|
|
40
|
+
s.name = PKG_NAME
|
41
|
+
s.version = PKG_VERSION
|
42
|
+
s.summary = "The JsTestCore library is the core javascript test server library used by several JS Test server libraries."
|
43
|
+
s.test_files = "spec/spec_suite.rb"
|
44
|
+
s.description = s.summary
|
45
|
+
|
46
|
+
s.files = PKG_FILES.to_a
|
47
|
+
s.require_path = 'lib'
|
48
|
+
|
49
|
+
s.has_rdoc = true
|
50
|
+
s.extra_rdoc_files = [ "README", "CHANGES" ]
|
51
|
+
s.rdoc_options = ["--main", "README", "--inline-source", "--line-numbers"]
|
52
|
+
|
53
|
+
s.test_files = Dir.glob('spec/*_spec.rb')
|
54
|
+
s.require_path = 'lib'
|
55
|
+
s.author = "Brian Takita"
|
56
|
+
s.email = "brian@pivotallabs.com"
|
57
|
+
s.homepage = "http://pivotallabs.com"
|
58
|
+
s.rubyforge_project = "pivotalrb"
|
59
|
+
s.add_dependency('Selenium')
|
60
|
+
s.add_dependency('thin', '=0.8.1')
|
61
|
+
end
|
62
|
+
|
63
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
64
|
+
pkg.need_zip = true
|
65
|
+
pkg.need_tar = true
|
66
|
+
end
|
67
|
+
|
68
|
+
def tag_release
|
69
|
+
dashed_version = PKG_VERSION.gsub('.', '-')
|
70
|
+
svn_user = "#{ENV["SVN_USER"]}@" || ""
|
71
|
+
`svn cp svn+ssh://#{svn_user}rubyforge.org/var/svn/pivotalrb/js_test_core/trunk svn+ssh://#{svn_user}rubyforge.org/var/svn/pivotalrb/js_test_core/tags/REL-#{dashed_version} -m 'Version #{PKG_VERSION}'`
|
72
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
gem "thin", ">=0.8.0"
|
3
|
+
|
4
|
+
dir = File.dirname(__FILE__)
|
5
|
+
$LOAD_PATH.unshift File.expand_path("#{dir}/../vendor/thin-rest/lib")
|
6
|
+
require "thin_rest"
|
7
|
+
|
8
|
+
# This causes errors to be printed to STDOUT.
|
9
|
+
Thin::Logging.silent = false
|
10
|
+
Thin::Logging.debug = true
|
11
|
+
|
12
|
+
require "fileutils"
|
13
|
+
require "tmpdir"
|
14
|
+
require "timeout"
|
15
|
+
require "cgi"
|
16
|
+
require "net/http"
|
17
|
+
require "selenium"
|
18
|
+
require "optparse"
|
19
|
+
|
20
|
+
require "#{dir}/js_test_core/extensions"
|
21
|
+
require "#{dir}/js_test_core/thin"
|
22
|
+
require "#{dir}/js_test_core/rack"
|
23
|
+
require "#{dir}/js_test_core/resources"
|
24
|
+
require "#{dir}/js_test_core/selenium"
|
25
|
+
|
26
|
+
require "#{dir}/js_test_core/client"
|
27
|
+
require "#{dir}/js_test_core/selenium_server_configuration"
|
28
|
+
require "#{dir}/js_test_core/server"
|
29
|
+
require "#{dir}/js_test_core/rails_server"
|
30
|
+
|
31
|
+
module JsTestCore
|
32
|
+
DEFAULT_HOST = "0.0.0.0"
|
33
|
+
DEFAULT_PORT = 8080
|
34
|
+
|
35
|
+
class << self
|
36
|
+
attr_accessor :core_path
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module JsTestCore
|
2
|
+
class Client
|
3
|
+
class ClientException < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
class InvalidStatusResponse < ClientException
|
7
|
+
end
|
8
|
+
|
9
|
+
class SuiteNotFound < ClientException
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def run(parameters={})
|
14
|
+
new(parameters).run
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_argv(argv)
|
18
|
+
params = {}
|
19
|
+
parser = OptionParser.new do |o|
|
20
|
+
o.banner = "JsTestCore Runner"
|
21
|
+
o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
|
22
|
+
|
23
|
+
o.on
|
24
|
+
o.on('-s', '--selenium_browser_start_command=selenium_browser_start_command', "The Selenium server command to start the browser. See http://selenium-rc.openqa.org/") do |selenium_browser_start_command|
|
25
|
+
params[:selenium_browser_start_command] = selenium_browser_start_command
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on('-h', '--selenium_host=SELENIUM_HOST', "The host name of the Selenium Server relative to where this file is executed") do |host|
|
29
|
+
params[:selenium_host] = host
|
30
|
+
end
|
31
|
+
|
32
|
+
o.on('-p', '--selenium_port=SELENIUM_PORT', "The port of the Selenium Server relative to where this file is executed") do |port|
|
33
|
+
params[:selenium_port] = port
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on('-u', '--spec_url=SPEC_URL', "The url of the js spec server, relative to the browsers running via the Selenium Server") do |spec_url|
|
37
|
+
params[:spec_url] = spec_url
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on_tail
|
41
|
+
end
|
42
|
+
parser.order!(argv)
|
43
|
+
run params
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :parameters, :query_string, :http, :suite_start_response, :last_poll_status, :last_poll_reason, :last_poll
|
48
|
+
def initialize(parameters)
|
49
|
+
@parameters = parameters
|
50
|
+
@query_string = SeleniumServerConfiguration.query_string_from(parameters)
|
51
|
+
end
|
52
|
+
|
53
|
+
def run
|
54
|
+
Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) do |@http|
|
55
|
+
start_runner
|
56
|
+
wait_for_suite_to_finish
|
57
|
+
end
|
58
|
+
report_result
|
59
|
+
end
|
60
|
+
|
61
|
+
def parts_from_query(query)
|
62
|
+
query.split('&').inject({}) do |acc, key_value_pair|
|
63
|
+
key, value = key_value_pair.split('=')
|
64
|
+
acc[key] = value
|
65
|
+
acc
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
def start_runner
|
71
|
+
@suite_start_response = http.post('/runners', query_string)
|
72
|
+
end
|
73
|
+
|
74
|
+
def wait_for_suite_to_finish
|
75
|
+
poll while suite_not_completed?
|
76
|
+
end
|
77
|
+
|
78
|
+
def report_result
|
79
|
+
case last_poll_status
|
80
|
+
when Resources::Suite::SUCCESSFUL_COMPLETION
|
81
|
+
STDOUT.puts "SUCCESS"
|
82
|
+
true
|
83
|
+
when Resources::Suite::FAILURE_COMPLETION
|
84
|
+
STDOUT.puts "FAILURE"
|
85
|
+
STDOUT.puts last_poll_reason
|
86
|
+
false
|
87
|
+
else
|
88
|
+
raise InvalidStatusResponse, "Invalid Status: #{last_poll_status}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def suite_not_completed?
|
93
|
+
last_poll_status.nil? || last_poll_status == Resources::Suite::RUNNING
|
94
|
+
end
|
95
|
+
|
96
|
+
def poll
|
97
|
+
@last_poll = http.get("/suites/#{suite_id}")
|
98
|
+
ensure_suite_exists!
|
99
|
+
parts = parts_from_query(last_poll.body)
|
100
|
+
@last_poll_status = parts['status']
|
101
|
+
@last_poll_reason = parts['reason']
|
102
|
+
end
|
103
|
+
|
104
|
+
def ensure_suite_exists!
|
105
|
+
if (400..499).include?(Integer(last_poll.code))
|
106
|
+
raise SuiteNotFound, "Could not find suite with id #{suite_id}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def suite_id
|
111
|
+
@suite_id ||= parts_from_query(suite_start_response.body)['suite_id']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module JsTestCore
|
2
|
+
class RailsServer < Server
|
3
|
+
class << self
|
4
|
+
def run(rails_root, server_options = {})
|
5
|
+
server_options[:Host] ||= DEFAULT_HOST
|
6
|
+
server_options[:Port] ||= DEFAULT_PORT
|
7
|
+
Server.instance = new(rails_root, server_options[:Host], server_options[:Port])
|
8
|
+
Server.instance.run server_options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(rails_root, host=DEFAULT_HOST, port=DEFAULT_PORT)
|
13
|
+
super(
|
14
|
+
"#{rails_root}/spec/javascripts",
|
15
|
+
"#{rails_root}/public/javascripts",
|
16
|
+
"#{rails_root}/public",
|
17
|
+
host,
|
18
|
+
port
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require "#{dir}/resources/runner"
|
3
|
+
require "#{dir}/resources/file"
|
4
|
+
require "#{dir}/resources/dir"
|
5
|
+
require "#{dir}/resources/file_not_found"
|
6
|
+
require "#{dir}/resources/specs/spec_file"
|
7
|
+
require "#{dir}/resources/specs/spec_dir"
|
8
|
+
require "#{dir}/resources/web_root"
|
9
|
+
require "#{dir}/resources/suite"
|
10
|
+
require "#{dir}/resources/suite_finish"
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module JsTestCore
|
2
|
+
module Resources
|
3
|
+
class Dir < File
|
4
|
+
route ANY do |env, name|
|
5
|
+
if file = file(name)
|
6
|
+
file
|
7
|
+
elsif subdir = subdir(name)
|
8
|
+
subdir
|
9
|
+
else
|
10
|
+
FileNotFound.new(env.merge(:name => name))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def get
|
15
|
+
connection.send_head
|
16
|
+
connection.send_body(::Dir.glob("#{absolute_path}/*").inject("") do |html, file|
|
17
|
+
file_basename = ::File.basename(file)
|
18
|
+
html << %Q|<a href="#{file_basename}">#{file_basename}</a>\n|
|
19
|
+
end)
|
20
|
+
end
|
21
|
+
|
22
|
+
def glob(pattern)
|
23
|
+
expanded_pattern = absolute_path + pattern
|
24
|
+
::Dir.glob(expanded_pattern).map do |absolute_globbed_path|
|
25
|
+
relative_globbed_path = absolute_globbed_path.gsub(absolute_path, relative_path)
|
26
|
+
File.new(env.merge(
|
27
|
+
:absolute_path => absolute_globbed_path,
|
28
|
+
:relative_path => relative_globbed_path
|
29
|
+
))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
def determine_child_paths(name)
|
35
|
+
absolute_child_path = "#{absolute_path}/#{name}"
|
36
|
+
relative_child_path = "#{relative_path}/#{name}"
|
37
|
+
[absolute_child_path, relative_child_path]
|
38
|
+
end
|
39
|
+
|
40
|
+
def file(name)
|
41
|
+
# N.B. Absolute_path and relative_path are methods. Do not shadow.
|
42
|
+
absolute_file_path, relative_file_path = determine_child_paths(name)
|
43
|
+
if ::File.exists?(absolute_file_path) && !::File.directory?(absolute_file_path)
|
44
|
+
Resources::File.new(env.merge(
|
45
|
+
:absolute_path => absolute_file_path,
|
46
|
+
:relative_path => relative_file_path
|
47
|
+
))
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def subdir(name)
|
54
|
+
# N.B. Absolute_path and relative_path are methods. Do not shadow.
|
55
|
+
absolute_dir_path, relative_dir_path = determine_child_paths(name)
|
56
|
+
if ::File.directory?(absolute_dir_path)
|
57
|
+
Resources::Dir.new(env.merge(
|
58
|
+
:absolute_path => absolute_dir_path,
|
59
|
+
:relative_path => relative_dir_path
|
60
|
+
))
|
61
|
+
else
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module JsTestCore
|
2
|
+
module Resources
|
3
|
+
class File < ThinRest::Resource
|
4
|
+
MIME_TYPES = {
|
5
|
+
'.js' => 'text/javascript',
|
6
|
+
'.css' => 'text/css',
|
7
|
+
'.png' => 'image/png',
|
8
|
+
'.jpg' => 'image/jpeg',
|
9
|
+
'.jpeg' => 'image/jpeg',
|
10
|
+
'.gif' => 'image/gif',
|
11
|
+
}
|
12
|
+
|
13
|
+
property :absolute_path, :relative_path
|
14
|
+
|
15
|
+
def get
|
16
|
+
extension = ::File.extname(absolute_path)
|
17
|
+
content_type = MIME_TYPES[extension] || 'text/html'
|
18
|
+
|
19
|
+
connection.terminate_after_sending do
|
20
|
+
connection.send_head(
|
21
|
+
200,
|
22
|
+
'Content-Type' => content_type,
|
23
|
+
'Last-Modified' => ::File.mtime(absolute_path).rfc822,
|
24
|
+
'Content-Length' => ::File.size(absolute_path)
|
25
|
+
)
|
26
|
+
::File.open(absolute_path) do |file|
|
27
|
+
while !file.eof?
|
28
|
+
connection.send_data(file.read(1024))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
return false unless other.class == self.class
|
35
|
+
absolute_path == other.absolute_path && relative_path == other.relative_path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|