bin/jspec in jspec-2.11.13 vs bin/jspec in jspec-3.0.0

- old
+ new

@@ -1,309 +1,178 @@ #!/usr/bin/env ruby -JSPEC_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) +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' +require 'src/project' +require 'src/installables' +require 'src/server' -RHINO = 'java org.mozilla.javascript.tools.shell.Main' - program :name, 'JSpec' -program :version, '2.11.13' +program :version, '3.0.0' program :description, 'JavaScript BDD Testing Framework' default_command :bind +JSpec::Project.load_commands_at '~/.jspec/commands' +JSpec::Project.load_commands_at 'spec/commands' +JSpec::Project.load_commands_at 'jspec/commands' + +command :stats do |c| + c.syntax = 'jspec stats [path ...]' + c.summary = 'View javascript source statistics' + c.description = 'View statistics for the given [paths], defaulting to /lib/**/*.js' + c.example 'View stats for all /lib javascript', 'jspec stats' + c.example 'View stats for all /public/javascript files', 'jspec stats public/javascript/*.js' + c.when_called do |paths, options| + paths = Dir['lib/**/*.js'] if paths.empty? + paths.each do |path| + contents = File.read path + say "%33s : \n" % $terminal.color(path, :bold) + say "%25s : %0.2f KiB\n" % ['size', File.size(path).to_f / 1024] + say "%25s : %d\n" % ['lines', contents.to_a.length] + say "%25s : %d\n" % ['comments', contents.scan(/\/\*.*?\*\/|\/\/.*?$/m).length] + say "%25s : %d\n" % ['functions', contents.scan(/function/i).length] + say "%25s : %d\n" % ['vars', contents.scan(/\bvar\b/).length] + say "\n" + end + end +end + +command :install do |c| + c.syntax = 'jspec install <project> [dest]' + c.summary = 'Install a project such as jQuery, Prototype, Rhino, etc.' + c.description = 'Install the given <project> to [dest] or spec/support/<project>. + When --release is not specified, the latest stable release will be used. + Currently the following projects are supported: + + - jquery + - jqueryui + - prototype + - mootools + - dojo + - envjs (--release not yet supported) + - rhino (--release not yet supported)' + c.option '-r', '--release STRING', 'Release version to install' + c.example 'Install jQuery to spec/support/jquery.js', 'jspec install jquery' + c.example 'Install jQuery 1.3.0 to spec/support/jquery.js', 'jspec install jquery --release 1.3.0' + c.example 'Install Prototype to spec/prototype.js', 'jspec install prototype spec' + c.example 'Install Prototype to spec/vendor/prototype.js', 'jspec install prototype spec/vendor' + c.when_called do |args, options| + name = args.shift or raise 'Project name required' + project = JSpec::Project.for '.' + if dest = args.shift + project.install name, :to => dest, :release => options.release + else + Dir.mkdir project.normalize('support') unless File.directory? project.normalize('support') + project.install name, :to => project.normalize('support'), :release => options.release + end + end +end + 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.' + running properly. + + To update a project to the recent version of JSpec use + `jspec help udpate` for more information.' 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 project in the current directory', 'jspec init' c.example 'Create a directory foo, initialized with a jspec template', 'jspec init foo' + c.example 'Rails application support', 'jspec init --rails' + c.example 'Rails application support, --rails is no longer required', 'jspec init' + c.example 'Freeze JSpec\'s library at spec/lib', 'jspec init --freeze' c.when_called do |args, options| - dest = args.shift || '.' - if options.rails - initialize_rails_at dest, options - else - initialize_at dest, options - end + JSpec::Project.for(dest = args.shift || '.').init! options.__hash__ 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, + c.description = 'Launch interactive Rhino 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' + if path.include? 'jspec.' "-f #{JSPEC_ROOT}/lib/#{path}" else "-f #{path}" end end say "JSpec #{program(:version)}" - `#{RHINO} #{paths.join(' ')} -f -` + `#{JSpec::Project::RHINO} #{paths.join(' ')} -f -` end end command :update do |c| - c.syntax = 'jspec update [path ...]' + c.syntax = 'jspec update [dest]' 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.description = 'Update JSpec release relative to [dest], this will allow you + to utilize the latest JSpec features. Execute from JSpec project + root without [dest] to update the default template spec files. + + This command supports regular projects, as well as those initialized + with --symlink and --freeze.' + c.example 'Update project in the current directory', 'jspec update' + c.example 'Update project in the directory specified', 'jspec update path/to/project' 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 + JSpec::Project.for(dest = args.shift || '.').update! 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. + c.description = 'Run specifications, defaulting [path] to 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. + Rhino: + The [path] is assumed to be spec/rhino.js unless specified. + Node.js: + The [path] is assumed to be spec/node.js unless specified. + 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 default browser', '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 'Run Rhino specs', 'jspec run --rhino' 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 '-N', '--node', 'Run specs using Node.js' 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 { exit 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 + JSpec::Project.for('.').run! args.first, options.__hash__ 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 - if path.include? 'dom' - contents = File.read(path).gsub 'JSPEC_ROOT/', root == JSPEC_ROOT ? "#{JSPEC_ROOT}/" : '' - else - contents = File.read(path).gsub 'JSPEC_ROOT', root - end - 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