mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
306 lines
9.0 KiB
Ruby
306 lines
9.0 KiB
Ruby
#!/usr/bin/env ruby
|
|
|
|
JSPEC_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
$:.unshift JSPEC_ROOT
|
|
|
|
require 'rubygems'
|
|
require 'commander/import'
|
|
require 'bind'
|
|
require 'fileutils'
|
|
require 'server/server'
|
|
|
|
RHINO = 'java org.mozilla.javascript.tools.shell.Main'
|
|
|
|
program :name, 'JSpec'
|
|
program :version, '2.11.7'
|
|
program :description, 'JavaScript BDD Testing Framework'
|
|
default_command :bind
|
|
|
|
command :init do |c|
|
|
c.syntax = 'jspec init [dest]'
|
|
c.summary = 'Initialize a JSpec project template'
|
|
c.description = 'Initialize a JSpec project template. Defaults to the current directory
|
|
when [dest] is not specified. The template includes several files for
|
|
running via Rhino, DOM, and the JSpec Rack server.
|
|
|
|
Additional switches --freeze, and --symlink are available in order
|
|
to preserve the version of JSpec at the time of initialization. Otherwise
|
|
incompatibilities from later versions may prevent your suite from
|
|
running properly.'
|
|
c.option '-R', '--rails', 'Initialize rails template from rails root directory'
|
|
c.option '-f', '--freeze', 'Copy the JSpec library'
|
|
c.option '-s', '--symlink', 'Symlink the JSpec library instead of copying it'
|
|
c.example 'Create a directory foo, initialized with a jspec template', 'jspec init foo'
|
|
c.when_called do |args, options|
|
|
dest = args.shift || '.'
|
|
if options.rails
|
|
initialize_rails_at dest, options
|
|
else
|
|
initialize_at dest, options
|
|
end
|
|
say "Template initialized at `#{dest}'"
|
|
end
|
|
end
|
|
|
|
command :shell do |c|
|
|
c.syntax = 'jspec shell [path ...]'
|
|
c.summary = 'JSpec interactive shell'
|
|
c.description = 'Launch interactive shell with jspec.js, jspec.shell.js,
|
|
and any [path]s given. Simply type "quit" or "exit" to
|
|
terminate the shell.'
|
|
c.example 'Run shell', 'jspec shell'
|
|
c.example 'Run shell with glob of files', 'jspec shell lib/*.js'
|
|
c.example 'Run shell with list of files', 'jspec shell lib/foo.js lib/bar.js'
|
|
c.when_called do |args, options|
|
|
paths = ['jspec.js', 'jspec.shell.js'] | args
|
|
paths.map! do |path|
|
|
if path.include? 'jspec'
|
|
"-f #{JSPEC_ROOT}/lib/#{path}"
|
|
else
|
|
"-f #{path}"
|
|
end
|
|
end
|
|
say "JSpec #{program(:version)}"
|
|
`#{RHINO} #{paths.join(' ')} -f -`
|
|
end
|
|
end
|
|
|
|
command :update do |c|
|
|
c.syntax = 'jspec update [path ...]'
|
|
c.summary = 'Update JSpec releases'
|
|
c.description = 'Update JSpec release in [paths], this will allow you to utilize
|
|
the latest JSpec features. Execute from JSpec project root without [paths] to
|
|
update the default template spec files.'
|
|
c.when_called do |args, options|
|
|
if args.empty?
|
|
if rails?
|
|
paths = 'jspec/spec.dom.html', 'jspec/spec.rhino.js'
|
|
else
|
|
paths = 'spec/spec.dom.html', 'spec/spec.rhino.js'
|
|
end
|
|
else
|
|
paths = args
|
|
end
|
|
update_version_in *paths
|
|
end
|
|
end
|
|
|
|
command :run do |c|
|
|
c.syntax = 'jspec run [path] [options]'
|
|
c.summary = 'Run specifications'
|
|
c.description = 'Run specifications, defaulting [path] to spec/spec.dom.html.
|
|
You will need to supply [path] if your specs do not reside
|
|
in this location. `run --bind` is the default sub-command of
|
|
jspec so you may simply execute `jspec` in order to bind execution
|
|
of your specs when a file is altered.
|
|
|
|
JSpec supports Rhino execution when installed. The [path] is assumed
|
|
to be spec/spec.rhino.js unless specified. See examples below for
|
|
using the --rhino switch.
|
|
|
|
JSpec\'s server is also available via --server, which defaults
|
|
the [path] to spec/server.html'
|
|
c.example 'Run once in Safari', 'jspec run'
|
|
c.example 'Run once in Safari and Firefox', 'jspec run --browsers Safari,Firefox'
|
|
c.example 'Run once in Opera, Firefox, and Chrome', 'jspec run --browsers opera,ff,chrome'
|
|
c.example 'Run custom spec file', 'jspec run foo.html'
|
|
c.example 'Auto-run browsers when a file is altered', 'jspec run --bind --browsers Safari,Firefox'
|
|
c.example 'Shortcut for the previous example', 'jspec --browsers Safari,Firefox'
|
|
c.example 'Auto-run rhino when a file is altered', 'jspec --rhino'
|
|
c.example 'Run Rhino specs at spec/rhino.js', 'jspec run --rhino'
|
|
c.example 'Run Rhino specs once', 'jspec run specs/something.js --rhino'
|
|
c.option '-b', '--browsers BROWSERS', Array, 'Specify browsers to test'
|
|
c.option '-p', '--paths PATHS', Array, 'Specify paths when binding, defaults to javascript within ./lib and ./spec'
|
|
c.option '-B', '--bind', 'Auto-run specs when source files or specs are altered'
|
|
c.option '-R', '--rhino', 'Run specs using Rhino'
|
|
c.option '-S', '--server', 'Run specs using the JSpec server'
|
|
c.option '-P', '--port NUMBER', Integer, 'Start JSpec server using the given port number'
|
|
c.when_called do |args, options|
|
|
|
|
# Rails
|
|
if rails?
|
|
options.default :paths => ['public/javascripts/**/*.js', 'jspec/**/*.js'], :port => 4444
|
|
else
|
|
options.default :paths => ['lib/**/*.js', 'spec/**/*.js'], :port => 4444
|
|
end
|
|
|
|
# Actions
|
|
if options.rhino
|
|
suite = args.shift || path_to('spec.rhino.js')
|
|
action = lambda { rhino suite }
|
|
elsif options.server
|
|
raise 'Cannot use --server with --bind' if options.bind
|
|
suite = args.shift || path_to('spec.server.html')
|
|
action = lambda { start_server suite, options }
|
|
else
|
|
suite = args.shift || path_to('spec.dom.html')
|
|
browsers = browsers_for options.browsers || ['safari']
|
|
action = lambda do
|
|
browsers.each do |browser|
|
|
browser.visit File.expand_path(suite)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Binding
|
|
if options.bind
|
|
listener = Bind::Listener.new :paths => options.paths, :interval => 1, :actions => [action], :debug => $stdout
|
|
listener.run!
|
|
else
|
|
action.call File.new(suite)
|
|
end
|
|
end
|
|
end
|
|
alias_command :bind, :run, '--bind'
|
|
|
|
##
|
|
# Initialize template at _dest_.
|
|
|
|
def initialize_at dest, options
|
|
unless Dir[dest + '/*'].empty?
|
|
abort unless agree "'#{dest}' is not empty; continue? "
|
|
end
|
|
|
|
copy_template_to 'default', dest
|
|
setup_lib_dir dest, options
|
|
replace_root_in dest, 'spec/spec.dom.html', 'spec/spec.rhino.js'
|
|
end
|
|
|
|
##
|
|
# Initialize rails template at _dest_.
|
|
|
|
def initialize_rails_at dest, options
|
|
unless looks_like_rails_root?(dest)
|
|
abort unless agree "'#{dest}' does not look like root of a rails project; continue? "
|
|
end
|
|
|
|
copy_template_to 'rails', "#{dest}/jspec"
|
|
setup_lib_dir "#{dest}/jspec", options
|
|
replace_root_in "#{dest}/jspec", 'spec.dom.html', 'spec.rhino.js'
|
|
end
|
|
|
|
##
|
|
# Copy template _name_ to _dest_.
|
|
|
|
def copy_template_to name, dest
|
|
FileUtils.mkdir_p dest
|
|
FileUtils.cp_r path_to_template(name), dest
|
|
end
|
|
|
|
##
|
|
# Return path to template _name_.
|
|
|
|
def path_to_template name
|
|
File.join JSPEC_ROOT, 'templates', name, '.'
|
|
end
|
|
|
|
##
|
|
# Resolve path to _file_. Supports rails and unbound projects.
|
|
|
|
def path_to file
|
|
rails? ? "jspec/#{file}" : "spec/#{file}"
|
|
end
|
|
|
|
##
|
|
# Execute _file_ with Rhino.
|
|
|
|
def rhino file
|
|
raise "#{file} not found" unless File.exists? file
|
|
system "#{RHINO} #{file}"
|
|
end
|
|
|
|
##
|
|
# Start server with _suite_ html and _options_.
|
|
|
|
def start_server suite, options
|
|
set :port, options.port
|
|
set :server, 'Mongrel'
|
|
enable :sessions
|
|
disable :logging
|
|
hook = File.expand_path path_to('server.rb')
|
|
load hook if File.exists? hook
|
|
JSpec::Server.new(suite, options.port).start(options.browsers ? browsers_for(options.browsers) : nil)
|
|
end
|
|
|
|
##
|
|
# Return array of browser instances for the given _names_.
|
|
|
|
def browsers_for names
|
|
names.map do |name|
|
|
begin
|
|
Browser.subclasses.find do |browser|
|
|
browser.matches_name? name
|
|
end.new
|
|
rescue
|
|
raise "Unsupported browser `#{name}'"
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
# Check if the current directory looks like a rails app.
|
|
|
|
def rails?
|
|
File.directory? 'jspec'
|
|
end
|
|
|
|
##
|
|
# Replace JSPEC_ROOT placeholder in _paths_ relative to _dest_.
|
|
|
|
def replace_root_in dest, *paths
|
|
if rails? && File.exist?("#{dest}/jspec/lib")
|
|
root = './jspec'
|
|
elsif File.exist?("#{dest}/spec/lib")
|
|
root = "./spec"
|
|
else
|
|
root = JSPEC_ROOT
|
|
end
|
|
|
|
paths.each do |path|
|
|
path = File.join dest, path
|
|
contents = File.read(path).gsub 'JSPEC_ROOT', root
|
|
File.open(path, 'w') { |file| file.write contents }
|
|
end
|
|
end
|
|
|
|
##
|
|
# Update JSpec version in _paths_. Matches jspec-TRIPLE
|
|
|
|
def update_version_in *paths
|
|
paths.each do |path|
|
|
next unless File.exists? path
|
|
contents = File.read(path).gsub /jspec-(\d+\.\d+\.\d+)/, "jspec-#{program(:version)}"
|
|
File.open(path, 'r+'){ |file| file.write contents }
|
|
say "Updated #{path}; #{$1} -> #{program(:version)}"
|
|
end
|
|
say "Finished updating JSpec"
|
|
end
|
|
|
|
##
|
|
# Check if _path_ looks like a rails root directory.
|
|
|
|
def looks_like_rails_root? path = '.'
|
|
File.directory? "#{path}/vendor"
|
|
end
|
|
|
|
##
|
|
# Copy or symlink library to the specified path.
|
|
|
|
def setup_lib_dir dest, options
|
|
return unless options.symlink || options.freeze
|
|
|
|
if rails?
|
|
dest = File.join dest, "lib"
|
|
else
|
|
dest = File.join dest, "spec", "lib"
|
|
end
|
|
|
|
from = File.join JSPEC_ROOT, "lib"
|
|
|
|
if options.symlink
|
|
FileUtils.symlink from, dest, :force => true
|
|
else
|
|
FileUtils.cp_r from, dest
|
|
end
|
|
end
|