sayso-js-test-driver-rails 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.gitmodules +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +21 -0
- data/LICENSE +19 -0
- data/README.markdown +118 -0
- data/Rakefile +12 -0
- data/js-test-driver-rails.gemspec +25 -0
- data/lib/js_test_driver.rb +6 -0
- data/lib/js_test_driver/config.rb +209 -0
- data/lib/js_test_driver/html_fixture.rb +40 -0
- data/lib/js_test_driver/runner.rb +232 -0
- data/lib/js_test_driver/tasks.rb +28 -0
- data/lib/js_test_driver/version.rb +3 -0
- data/test/fixtures/a.html +1 -0
- data/test/fixtures/b.html +1 -0
- data/test/fixtures/baz/a.html +1 -0
- data/test/fixtures/c.html +1 -0
- data/test/fixtures/foo/a.html +1 -0
- data/test/fixtures/foo/bar/a.html +1 -0
- data/test/fixtures/hello.txt +1 -0
- data/test/integration/sample_test.rb +15 -0
- data/test/sample/config/js_test_driver.rb +11 -0
- data/test/sample/lib/calculator.js +15 -0
- data/test/sample/specs/calculator_spec.js +19 -0
- data/test/sample/specs/spec_helper.js +4 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/config_test.rb +270 -0
- data/test/unit/html_fixture_test.rb +70 -0
- data/test/unit/runner_test.rb +107 -0
- data/vendor/JasmineAdapter.js +179 -0
- data/vendor/VERSIONS +3 -0
- data/vendor/coverage.jar +0 -0
- data/vendor/jasmine.js +2435 -0
- data/vendor/js_test_driver.jar +0 -0
- metadata +129 -0
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
js-test-driver-rails (0.4.2)
|
5
|
+
json
|
6
|
+
rake
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
json (1.4.6)
|
12
|
+
mocha (0.9.9)
|
13
|
+
rake
|
14
|
+
rake (0.8.7)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
js-test-driver-rails!
|
21
|
+
mocha
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 by Adam Pohorecki
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
JS Test Driver Rails
|
2
|
+
====================
|
3
|
+
|
4
|
+
js-test-driver-rails is a thin wrapper for the JsTestDriver library: http://code.google.com/p/js-test-driver/
|
5
|
+
|
6
|
+
Configuration
|
7
|
+
------------
|
8
|
+
|
9
|
+
To take advantage of js-test-driver-rails, you should create a js_test_driver.rb file in your RAILS_ROOT/config/ directory.
|
10
|
+
|
11
|
+
The file may contain following directives:
|
12
|
+
|
13
|
+
# the paths are relative to the current directory, but you can use absolute paths too
|
14
|
+
# this is different from the JsTestDriver which does not allow you to use absolute paths in the config file
|
15
|
+
|
16
|
+
# files to be included
|
17
|
+
# you can use Ruby globbing syntax (spec/js/**/*_spec.js), which will be automatically expanded
|
18
|
+
includes 'foo', 'bar', 'public/javascripts/*.js'
|
19
|
+
|
20
|
+
# files to be excluded, useful with globbing
|
21
|
+
excludes 'public/javascripts/fail.js'
|
22
|
+
|
23
|
+
# the host to which the test runner will connect, by default 'localhost'
|
24
|
+
host 'my-laptop'
|
25
|
+
|
26
|
+
# the port to which test runner will connect, and on which the test server will start, by default 4224
|
27
|
+
port 6666
|
28
|
+
|
29
|
+
# you can specify the default browsers which will be captured
|
30
|
+
browser 'firefox'
|
31
|
+
|
32
|
+
Note, that this is a ruby file, so the file/browser list can be generated dynamically - it's completely up to you.
|
33
|
+
|
34
|
+
For example in our project we examine a list of known browsers to determine the ones installed on the developer's system, and define only those that were found.
|
35
|
+
|
36
|
+
Similarly we get the list of .js files to include from our asset packaging solution.
|
37
|
+
|
38
|
+
HTML Fixtures
|
39
|
+
-------------
|
40
|
+
|
41
|
+
js-test-driver-rails also allows you to define HTML fixtures easily.
|
42
|
+
|
43
|
+
Imagine you have a directory structure like this:
|
44
|
+
|
45
|
+
RAILS_ROOT:
|
46
|
+
test/
|
47
|
+
js/
|
48
|
+
fixtures/
|
49
|
+
foo/
|
50
|
+
a.html
|
51
|
+
a.html
|
52
|
+
|
53
|
+
Then by defining the fixtures directory in your config file:
|
54
|
+
|
55
|
+
fixtures "test/js/fixtures"
|
56
|
+
|
57
|
+
At runtime, your tests will have access to the contents of the fixture files:
|
58
|
+
|
59
|
+
htmlFixtures.all["a"] // contents of the test/js/fixtures/a.html
|
60
|
+
htmlFixtures.all["foo/a"] // contents of the test/js/fixtures/foo/a.html
|
61
|
+
|
62
|
+
You can customize the namespace and fixture container name:
|
63
|
+
|
64
|
+
# the fixtures will be accessible through myApp.html["<fixture name goes here>"]
|
65
|
+
fixtures "test/js/fixtures", :name => "html", :namespace => "myApp"
|
66
|
+
|
67
|
+
Using Jasmine
|
68
|
+
-------------
|
69
|
+
|
70
|
+
By default JsTestDriver comes with a pretty simple Test::Unit like testing framework.
|
71
|
+
However it supports a couple of other frameworks, including Jasmine (http://pivotal.github.com/jasmine/), which is an RSpec-like BDD framework.
|
72
|
+
|
73
|
+
If you want to user Jasmine, simply add:
|
74
|
+
|
75
|
+
enable_jasmine
|
76
|
+
|
77
|
+
in your config file, somewhere before including your test files and you are golden:)
|
78
|
+
|
79
|
+
Measuring code coverage
|
80
|
+
-----------------------
|
81
|
+
|
82
|
+
JsTestDriver has a pretty cool feature of being able to measure code coverage. To enable this in your config, you just need to add:
|
83
|
+
|
84
|
+
measure_coverage
|
85
|
+
|
86
|
+
in your config file.
|
87
|
+
|
88
|
+
You need to have lcov installed for the HTML report to be generated:
|
89
|
+
|
90
|
+
sudo apt-get install lcov
|
91
|
+
|
92
|
+
The HTML coverage report will be saved in the .js_test_driver/tests/coverage directory.
|
93
|
+
|
94
|
+
Rake tasks
|
95
|
+
----------
|
96
|
+
|
97
|
+
This gem comes with some rake tasks, which you should require in your Rake file:
|
98
|
+
|
99
|
+
require "js_test_driver/tasks"
|
100
|
+
|
101
|
+
To start the js test driver server:
|
102
|
+
|
103
|
+
rake js_test_driver:start_server
|
104
|
+
|
105
|
+
To capture the default (or specified) browsers
|
106
|
+
|
107
|
+
rake js_test_driver:capture_browsers [BROWSERS=foo,bar,baz]
|
108
|
+
|
109
|
+
To run the tests (all or the specified ones)
|
110
|
+
|
111
|
+
rake js_test_driver:run_tests [TESTS=TestCase[.testMethod]]
|
112
|
+
|
113
|
+
To run the server, capture the browsers and run tests all in one command
|
114
|
+
|
115
|
+
rake js_test_driver:run [TESTS=TestCase[.testMethod]] [BROWSERS=foo,bar,baz] [OUTPUT_XML=1 | OUTPUT_PATH=/some/dir] [CAPTURE_CONSOLE=1]
|
116
|
+
|
117
|
+
This last task is mostly useful on CI, because it's much faster to run the server and capture the browsers once and then run the tests again and again in development mode.
|
118
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "js_test_driver/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sayso-js-test-driver-rails"
|
7
|
+
s.version = JsTestDriver::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["SaySo"]
|
10
|
+
s.email = ["sayso@truvolabs.com"]
|
11
|
+
s.homepage = "http://github.com/sayso/js-test-driver-rails"
|
12
|
+
s.summary = "A wrapper for JsTestDriver for use with ruby/rails projects"
|
13
|
+
s.description = "Use ruby to configure JsTestDriver, capture browsers and run tests."
|
14
|
+
|
15
|
+
s.rubyforge_project = "js-test-driver-rails"
|
16
|
+
|
17
|
+
s.add_dependency 'json'
|
18
|
+
s.add_dependency 'rake'
|
19
|
+
s.add_development_dependency 'mocha'
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'js_test_driver', 'config'))
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'js_test_driver', 'runner'))
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'js_test_driver', 'html_fixture'))
|
@@ -0,0 +1,209 @@
|
|
1
|
+
module JsTestDriver
|
2
|
+
# The Config class represents the YAML config file that is passed to JsTestDriver
|
3
|
+
#
|
4
|
+
# includes corresponds to load
|
5
|
+
# excludes corresponds to exclude
|
6
|
+
# server can be configures either using server, or host and port
|
7
|
+
#
|
8
|
+
# The configuration is very basic, however the fact that it is done in Ruby, gives the
|
9
|
+
# user a significant amount of freedom in terms of what is and is not loaded, and so on
|
10
|
+
class Config
|
11
|
+
|
12
|
+
def initialize(attributes = {})
|
13
|
+
self.attributes = attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
# Adds a file to be loaded, the path *must* be relative to the root_dir (which is the current dir by default)
|
17
|
+
#
|
18
|
+
# JsTestDriver supports globbing
|
19
|
+
def includes(*paths)
|
20
|
+
self.included_files.concat(expand_globs(paths))
|
21
|
+
end
|
22
|
+
|
23
|
+
# Files specified here will not be loaded, it's useful when combined with globbing in includes
|
24
|
+
#
|
25
|
+
# paths should be relative to root_dir
|
26
|
+
def excludes(*paths)
|
27
|
+
self.excluded_files.concat(expand_globs(paths))
|
28
|
+
end
|
29
|
+
|
30
|
+
# Defines a browser to be captured by default
|
31
|
+
#
|
32
|
+
# This should be a string with no spaces (if you need to pass parameters to the browser you will
|
33
|
+
# need to create a shell script ans put it's name here)
|
34
|
+
def browser(*browsers)
|
35
|
+
browsers.each do |browser|
|
36
|
+
self.browsers << browser
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Defines a HTML fixture directory
|
41
|
+
#
|
42
|
+
# the first argument is the directory to scan for html fixtures
|
43
|
+
# you can pass also :name and :namespace arguments to define the name and the namespace of the fixture
|
44
|
+
#
|
45
|
+
# the fixtures will be accessible through:
|
46
|
+
# namespace.name["file_name_without the html extension"]
|
47
|
+
#
|
48
|
+
# by default the namespace is called htmlFixtures
|
49
|
+
# and the fixture name is called all
|
50
|
+
def fixtures(directory, opts = {})
|
51
|
+
fixture = JsTestDriver::HtmlFixture.new(directory, opts[:name], opts[:namespace])
|
52
|
+
if html_fixtures.detect{|f| f.name == fixture.name && f.namespace == fixture.namespace}
|
53
|
+
raise ArgumentError.new("Fixture #{fixture.namespace}.#{fixture.name} already defined!")
|
54
|
+
end
|
55
|
+
html_fixtures << fixture
|
56
|
+
end
|
57
|
+
|
58
|
+
# Includes the bundled with the gem jasmine js file and an adapter for jasmine
|
59
|
+
#
|
60
|
+
# There's no hacks or modifications here, so this method is just for the users convenience
|
61
|
+
def enable_jasmine
|
62
|
+
includes File.join(vendor_directory, "jasmine.js")
|
63
|
+
includes File.join(vendor_directory, "JasmineAdapter.js")
|
64
|
+
end
|
65
|
+
|
66
|
+
# Adds a JsTestDriver plugin for measuring coverage to the configuration
|
67
|
+
def measure_coverage
|
68
|
+
@measure_coverage = true
|
69
|
+
self.plugins << {
|
70
|
+
'name' => 'coverage',
|
71
|
+
'jar' => File.join(vendor_directory, 'coverage.jar'),
|
72
|
+
'module' => 'com.google.jstestdriver.coverage.CoverageModule'
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def measure_coverage?
|
77
|
+
!!@measure_coverage
|
78
|
+
end
|
79
|
+
|
80
|
+
# Plugins to include in the config
|
81
|
+
def plugins
|
82
|
+
@plugins ||= []
|
83
|
+
end
|
84
|
+
|
85
|
+
# config variable which has a regular setter,
|
86
|
+
# but also can be set by calling the "getter" with an argument
|
87
|
+
# and if called without an argument the getter will return the passed block
|
88
|
+
#
|
89
|
+
# Ex.
|
90
|
+
# A.define_config_variable(:foo) { @foo || "hello" }
|
91
|
+
# a = A.new
|
92
|
+
# a.foo # returns "hello"
|
93
|
+
# a.foo "foo"
|
94
|
+
# a.foo # returns "foo"
|
95
|
+
# a.foo = "bar"
|
96
|
+
# a.foo # returns "bar"
|
97
|
+
def self.define_config_variable(name, &block)
|
98
|
+
attr_writer name
|
99
|
+
|
100
|
+
define_method(name) do |*values|
|
101
|
+
unless values.empty?
|
102
|
+
self.send("#{name}=", values.first)
|
103
|
+
else
|
104
|
+
instance_eval(&block)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# the port the server will use, by default 4224
|
110
|
+
define_config_variable(:port) { @port ||= 4224 }
|
111
|
+
|
112
|
+
# the host of the server, by default localhost
|
113
|
+
define_config_variable(:host) { @host ||= 'localhost' }
|
114
|
+
|
115
|
+
# the whole server string - unless overwritten will be constructed from host and port,
|
116
|
+
# if you specify server, host and port will be ignored
|
117
|
+
# but you still need to specify port for starting the server
|
118
|
+
define_config_variable(:server) { @server || "http://#{host}:#{port}" }
|
119
|
+
|
120
|
+
# the base path to which all of the paths in the config file are relative
|
121
|
+
define_config_variable(:base_path) { @base_path ||= '/' }
|
122
|
+
|
123
|
+
def included_files
|
124
|
+
@includes ||= []
|
125
|
+
end
|
126
|
+
|
127
|
+
def excluded_files
|
128
|
+
@excludes ||= []
|
129
|
+
end
|
130
|
+
|
131
|
+
def html_fixtures
|
132
|
+
@html_fixtures ||= []
|
133
|
+
end
|
134
|
+
|
135
|
+
attr_writer :browsers
|
136
|
+
|
137
|
+
def browsers
|
138
|
+
@browsers ||= []
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
hash = {'server' => server, 'basepath' => base_path}
|
143
|
+
hash['load'] = loaded_files unless loaded_files.empty?
|
144
|
+
hash['exclude'] = map_paths(excluded_files) unless excluded_files.empty?
|
145
|
+
hash['plugin'] = plugins unless plugins.empty?
|
146
|
+
return hash.to_yaml
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.parse(string)
|
150
|
+
config = new
|
151
|
+
config.instance_eval(string)
|
152
|
+
return config
|
153
|
+
end
|
154
|
+
|
155
|
+
attr_writer :config_dir
|
156
|
+
|
157
|
+
# this is where the config files are saved (ex. RAILS_ROOT/.js_test_driver)
|
158
|
+
def config_dir
|
159
|
+
@config_dir ||= File.expand_path(".")
|
160
|
+
end
|
161
|
+
|
162
|
+
def save_fixtures
|
163
|
+
html_fixtures.each do |fixture|
|
164
|
+
path = fixture_file_name(fixture)
|
165
|
+
FileUtils.mkdir_p(File.dirname(path))
|
166
|
+
File.open(path, "w+") do |f|
|
167
|
+
f.puts fixture.to_s
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def vendor_directory
|
175
|
+
this_directory = File.dirname(__FILE__)
|
176
|
+
return File.expand_path(File.join('..', '..', 'vendor'), this_directory)
|
177
|
+
end
|
178
|
+
|
179
|
+
def expand_globs(paths)
|
180
|
+
with_expanded_paths = paths.map{|path| File.expand_path(path)}
|
181
|
+
return with_expanded_paths.map{|path| path.include?('*') ? Dir[path].sort : path}.flatten
|
182
|
+
end
|
183
|
+
|
184
|
+
def fixture_file_name(fixture)
|
185
|
+
File.expand_path(File.join(config_dir, "fixtures", fixture.namespace, "#{fixture.name}.js"))
|
186
|
+
end
|
187
|
+
|
188
|
+
def loaded_files
|
189
|
+
files = included_files + html_fixtures.collect { |fixture| fixture_file_name(fixture) }
|
190
|
+
|
191
|
+
map_paths(files)
|
192
|
+
end
|
193
|
+
|
194
|
+
def path_relative_to_base_path(path)
|
195
|
+
path.gsub(/^#{Regexp.escape(base_path)}/, '')
|
196
|
+
end
|
197
|
+
|
198
|
+
def map_paths(files)
|
199
|
+
files.map{|file| path_relative_to_base_path(file)}
|
200
|
+
end
|
201
|
+
|
202
|
+
def attributes=(values)
|
203
|
+
values.each do |attr, value|
|
204
|
+
self.send("#{attr}=", value)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module JsTestDriver
|
2
|
+
# This is a class that given a directory name, puts all its *.html children
|
3
|
+
# into a javascript file, so that they can later be used in the tests
|
4
|
+
class HtmlFixture
|
5
|
+
|
6
|
+
attr_reader :name, :namespace
|
7
|
+
|
8
|
+
def initialize(directory_name, name = nil, namespace = nil)
|
9
|
+
@name = name || "all"
|
10
|
+
@namespace = namespace || "htmlFixtures"
|
11
|
+
@data = {}
|
12
|
+
|
13
|
+
load_data(directory_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
@data
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
<<JS
|
22
|
+
if (typeof(#{namespace}) === 'undefined') { #{namespace} = {}; }
|
23
|
+
#{namespace}.#{name} = #{self.to_h.to_json};
|
24
|
+
JS
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def load_data(directory_name)
|
30
|
+
full_path = File.expand_path(directory_name)
|
31
|
+
files = Dir["#{full_path}/**/*.html"]
|
32
|
+
|
33
|
+
files.each do |file|
|
34
|
+
name = file.gsub(/^#{full_path}\//, '').gsub(/\.html$/, '')
|
35
|
+
@data[name] = File.read(file)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|