jasmine 2.0.0.rc2 → 2.0.0.rc3

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -11
  3. data/Gemfile +4 -2
  4. data/HOW_TO_TEST.markdown +1 -1
  5. data/README.markdown +23 -14
  6. data/RELEASE.markdown +6 -13
  7. data/Rakefile +21 -23
  8. data/jasmine.gemspec +9 -16
  9. data/{generators/jasmine/templates/jasmine-example/spec → lib/generators/jasmine/examples/templates/spec/javascripts/helpers/jasmine_examples}/SpecHelper.js +0 -0
  10. data/lib/generators/jasmine/examples/templates/spec/javascripts/jasmine_examples/PlayerSpec.js +1 -1
  11. data/lib/generators/jasmine/install/templates/spec/javascripts/support/jasmine.yml +15 -2
  12. data/lib/generators/jasmine/install/templates/spec/javascripts/support/jasmine_helper.rb +2 -2
  13. data/lib/jasmine.rb +5 -7
  14. data/lib/jasmine/asset_bundle.rb +9 -10
  15. data/lib/jasmine/command_line_install.txt +13 -0
  16. data/lib/jasmine/command_line_tool.rb +100 -58
  17. data/lib/jasmine/config.rb +25 -13
  18. data/lib/jasmine/configuration.rb +21 -16
  19. data/lib/jasmine/dependencies.rb +1 -1
  20. data/lib/jasmine/formatters/console.rb +21 -13
  21. data/lib/jasmine/formatters/exit_code.rb +21 -0
  22. data/lib/jasmine/formatters/multi.rb +25 -0
  23. data/lib/jasmine/result.rb +46 -0
  24. data/lib/jasmine/run.html.erb +3 -1
  25. data/lib/jasmine/runners/phantom_jasmine_run.js +54 -0
  26. data/lib/jasmine/runners/phantom_js.rb +29 -0
  27. data/lib/jasmine/tasks/jasmine.rake +42 -21
  28. data/lib/jasmine/version.rb +1 -1
  29. data/spec/configuration_spec.rb +34 -72
  30. data/spec/fixture/coffee_spec.coffee +3 -0
  31. data/spec/fixture/failing_runner.rb +9 -0
  32. data/spec/fixture/failing_test.js +5 -0
  33. data/spec/fixture/large_test_suite_spec.js +20 -0
  34. data/spec/jasmine_command_line_tool_spec.rb +94 -52
  35. data/spec/jasmine_pojs_spec.rb +37 -21
  36. data/spec/jasmine_rails_spec.rb +89 -49
  37. data/spec/lib/jasmine/formatters/console_spec.rb +50 -35
  38. data/spec/lib/jasmine/formatters/multi_spec.rb +17 -0
  39. data/spec/performance/phantom_js_runner_performance_spec.rb +23 -0
  40. data/spec/result_spec.rb +34 -0
  41. data/spec/spec_helper.rb +40 -16
  42. metadata +34 -84
  43. data/generators/jasmine/jasmine_generator.rb +0 -25
  44. data/generators/jasmine/templates/INSTALL +0 -9
  45. data/generators/jasmine/templates/jasmine-example/spec/PlayerSpec.js +0 -58
  46. data/generators/jasmine/templates/jasmine-example/src/Player.js +0 -22
  47. data/generators/jasmine/templates/jasmine-example/src/Song.js +0 -7
  48. data/generators/jasmine/templates/lib/tasks/jasmine.rake +0 -8
  49. data/generators/jasmine/templates/spec/javascripts/support/jasmine-rails.yml +0 -81
  50. data/generators/jasmine/templates/spec/javascripts/support/jasmine.yml +0 -88
  51. data/generators/jasmine/templates/spec/javascripts/support/jasmine_helper.rb +0 -12
  52. data/lib/generators/jasmine/examples/templates/spec/javascripts/helpers/SpecHelper.js +0 -15
  53. data/lib/jasmine/firebug/firebug-1.6.2.xpi +0 -0
  54. data/lib/jasmine/firebug/firebug-1.7.0.xpi +0 -0
  55. data/lib/jasmine/firebug/firebug-license.txt +0 -30
  56. data/lib/jasmine/firebug/firebug.rb +0 -30
  57. data/lib/jasmine/formatters/base.rb +0 -9
  58. data/lib/jasmine/formatters/junit_xml.rb +0 -47
  59. data/lib/jasmine/reporters/api_reporter.rb +0 -38
  60. data/lib/jasmine/results.rb +0 -38
  61. data/lib/jasmine/results_processor.rb +0 -38
  62. data/lib/jasmine/run_specs.rb +0 -33
  63. data/lib/jasmine/runners/http.rb +0 -33
  64. data/lib/jasmine/selenium_driver.rb +0 -45
  65. data/spec/asset_expander_spec.rb +0 -13
  66. data/spec/asset_pipeline_mapper_spec.rb +0 -19
  67. data/spec/jasmine_command_line_tool_rakeless_spec.rb +0 -20
  68. data/spec/lib/jasmine/formatters/base_spec.rb +0 -9
  69. data/spec/lib/jasmine/formatters/junit_xml_spec.rb +0 -55
  70. data/spec/lib/jasmine/reporters/api_reporter_spec.rb +0 -53
  71. data/spec/lib/jasmine/runners/http_spec.rb +0 -21
  72. data/spec/results_processor_spec.rb +0 -3
  73. data/spec/results_spec.rb +0 -69
  74. data/spec/support/fake_selenium_driver.rb +0 -35
@@ -1,4 +1,5 @@
1
1
  module Jasmine
2
+ ConfigNotFound = Class.new(Exception)
2
3
  require 'yaml'
3
4
  require 'erb'
4
5
  def self.configure(&block)
@@ -25,7 +26,15 @@ module Jasmine
25
26
  @config.jasmine_css_files = lambda { core_config.css_files }
26
27
  @config.add_rack_path(jasmine_path, lambda { Rack::File.new(config.jasmine_dir) })
27
28
  @config.add_rack_path(boot_path, lambda { Rack::File.new(config.boot_dir) })
28
- @config.add_rack_path(spec_path, lambda { Rack::File.new(config.spec_dir) })
29
+ if Jasmine::Dependencies.use_asset_pipeline?
30
+ @config.add_rack_path(spec_path, lambda {
31
+ sprockets_spec_env = Sprockets::Environment.new
32
+ sprockets_spec_env.append_path @config.spec_dir
33
+ sprockets_spec_env
34
+ })
35
+ else
36
+ @config.add_rack_path(spec_path, lambda { Rack::File.new(config.spec_dir) })
37
+ end
29
38
  @config.add_rack_path(image_path, lambda { Rack::File.new(core_config.images_dir) })
30
39
  @config.add_rack_path(src_path, lambda {
31
40
  Rack::Cascade.new([
@@ -42,23 +51,24 @@ module Jasmine
42
51
  asset_expander = Jasmine::AssetExpander.new(Jasmine::AssetBundle.factory)
43
52
  Jasmine::AssetPipelineMapper.new(config, asset_expander.method(:expand))
44
53
  })
45
- @config.add_rack_path(Rails.application.config.assets.prefix, lambda {
46
- # In order to have asset helpers like asset_path and image_path, we need to require 'action_view/base'. This
47
- # triggers run_load_hooks on action_view which, in turn, causes sprockets/railtie to load the Sprockets asset
48
- # helpers. Alternatively, you can include the helpers yourself without loading action_view/base:
49
- Rails.application.assets.context_class.instance_eval do
50
- if Jasmine::Dependencies.rails3?
51
- include ::Sprockets::Helpers::IsolatedHelper
52
- include ::Sprockets::Helpers::RailsHelper
53
- end
54
- if Jasmine::Dependencies.rails4?
55
- include ::Sprockets::Rails::Helper
56
- end
54
+ # In order to have asset helpers like asset_path and image_path, we need to require 'action_view/base'. This
55
+ # triggers run_load_hooks on action_view which, in turn, causes sprockets/railtie to load the Sprockets asset
56
+ # helpers. Alternatively, you can include the helpers yourself without loading action_view/base:
57
+ Rails.application.assets.context_class.instance_eval do
58
+ if Jasmine::Dependencies.rails3?
59
+ include ::Sprockets::Helpers::IsolatedHelper
60
+ include ::Sprockets::Helpers::RailsHelper
57
61
  end
62
+ if Jasmine::Dependencies.rails4?
63
+ include ::Sprockets::Rails::Helper
64
+ end
65
+ end
66
+ @config.add_rack_path(Rails.application.config.assets.prefix, lambda {
58
67
  Rails.application.assets
59
68
  })
60
69
  end
61
70
 
71
+ @config.runner = lambda { |formatter, jasmine_server_url| Jasmine::Runners::PhantomJs.new(formatter, jasmine_server_url, 50) }
62
72
  end
63
73
 
64
74
  def self.config
@@ -88,6 +98,8 @@ module Jasmine
88
98
  config.spec_files = lambda { yaml_config.helpers + yaml_config.spec_files }
89
99
  end
90
100
  require yaml_config.spec_helper if File.exist?(yaml_config.spec_helper)
101
+ else
102
+ raise ConfigNotFound, "Unable to load jasmine config from #{path}"
91
103
  end
92
104
  end
93
105
 
@@ -5,11 +5,9 @@ module Jasmine
5
5
  attr_accessor :jasmine_path, :spec_path, :boot_path, :src_path, :image_path
6
6
  attr_accessor :jasmine_dir, :spec_dir, :boot_dir, :src_dir, :images_dir
7
7
  attr_accessor :formatters
8
- #TODO: these are largely client concerns, move them.
9
- attr_accessor :port, :browser, :host, :result_batch_size
10
- attr_accessor :selenium_server, :selenium_server_port, :webdriver
11
- attr_accessor :junit_xml_path
12
- attr_accessor :spec_format, :jasmine_port
8
+ attr_accessor :host
9
+ attr_accessor :spec_format
10
+ attr_accessor :runner
13
11
 
14
12
  def initialize()
15
13
  @rack_paths = {}
@@ -21,12 +19,11 @@ module Jasmine
21
19
  @boot_files = lambda { [] }
22
20
  @src_files = lambda { [] }
23
21
  @spec_files = lambda { [] }
22
+ @runner = lambda { |config| }
24
23
 
25
24
  @formatters = [Jasmine::Formatters::Console]
26
25
 
27
- @browser = 'firefox'
28
- @junit_xml_path = Dir.getwd
29
- @jasmine_port = 8888
26
+ @server_port = 8888
30
27
  end
31
28
 
32
29
  def css_files
@@ -61,22 +58,30 @@ module Jasmine
61
58
  @path_mappers << mapper.call(self)
62
59
  end
63
60
 
64
- def port
65
- @port ||= Jasmine.find_unused_port
61
+ def server_port=(port)
62
+ @server_port = port
66
63
  end
67
64
 
68
- def host
69
- @host || 'http://localhost'
65
+ def ci_port=(port)
66
+ @ci_port = port
70
67
  end
71
68
 
72
- def result_batch_size
73
- @result_batch_size || 50
69
+ def port(server_type)
70
+ if server_type == :server
71
+ @server_port
72
+ else
73
+ @ci_port ||= Jasmine.find_unused_port
74
+ end
75
+ end
76
+
77
+ def host
78
+ @host || 'http://localhost'
74
79
  end
75
80
 
76
81
  private
77
82
 
78
- def map(paths, type)
79
- @path_mappers.inject(paths.call) do |paths, mapper|
83
+ def map(path_procs, type)
84
+ @path_mappers.inject(path_procs.call) do |paths, mapper|
80
85
  if mapper.respond_to?("map_#{type}_paths")
81
86
  mapper.send("map_#{type}_paths", paths)
82
87
  else
@@ -23,7 +23,7 @@ module Jasmine
23
23
  end
24
24
 
25
25
  def use_asset_pipeline?
26
- (rails3? || rails4?) && Rails.respond_to?(:application) && Rails.application.respond_to?(:assets) && Rails.application.assets
26
+ (rails3? || rails4?) && Rails.respond_to?(:application) && Rails.application.respond_to?(:assets)
27
27
  end
28
28
 
29
29
  private
@@ -1,25 +1,33 @@
1
1
  module Jasmine
2
2
  module Formatters
3
- class Console < BaseFormatter
4
- def format
5
- puts failures
6
- puts summary
3
+ class Console
4
+ def initialize(outputter = Kernel.method(:puts))
5
+ @results = []
6
+ @outputter = outputter
7
7
  end
8
8
 
9
- def summary
10
- summary = "#{pluralize(results.size, 'spec')}, " +
11
- "#{pluralize(results.failures.size, 'failure')}"
9
+ def format(results_batch)
10
+ outputter.call(failures(results_batch))
11
+ @results += results_batch
12
+ end
12
13
 
13
- summary += ", #{pluralize(results.pending_specs.size, 'pending spec')}" unless results.pending_specs.empty?
14
+ def done
15
+ failure_count = results.count(&:failed?)
16
+ pending_count = results.count(&:pending?)
17
+ summary = "#{pluralize(results.size, 'spec')}, " +
18
+ "#{pluralize(failure_count, 'failure')}"
14
19
 
15
- summary
16
- end
20
+ summary += ", #{pluralize(pending_count, 'pending spec')}" if pending_count > 0
17
21
 
18
- def failures
19
- results.failures.map { |f| failure_message(f) }.join("\n\n")
22
+ outputter.call(summary)
20
23
  end
21
24
 
22
25
  private
26
+ attr_reader :results, :outputter
27
+
28
+ def failures(results)
29
+ results.select(&:failed?).map { |f| failure_message(f) }.join("\n\n")
30
+ end
23
31
 
24
32
  def pluralize(count, str)
25
33
  word = (count == 1) ? str : str + 's'
@@ -42,4 +50,4 @@ module Jasmine
42
50
  end
43
51
  end
44
52
  end
45
- end
53
+ end
@@ -0,0 +1,21 @@
1
+ module Jasmine
2
+ module Formatters
3
+ class ExitCode
4
+ def initialize
5
+ @results = []
6
+ end
7
+
8
+ def format(results)
9
+ @results += results
10
+ end
11
+
12
+ def done
13
+ end
14
+
15
+ def exit_code
16
+ @results.detect(&:failed?) ? 1 : 0
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,25 @@
1
+ module Jasmine
2
+ module Formatters
3
+ class Multi
4
+ def initialize(formatters)
5
+ @formatters = formatters
6
+ end
7
+
8
+ def format(results)
9
+ go(:format, results)
10
+ end
11
+
12
+ def done
13
+ go(:done)
14
+ end
15
+
16
+ private
17
+
18
+ def go(method, *args)
19
+ (@formatters || []).each do |formatter|
20
+ formatter.public_send(method, *args)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ module Jasmine
2
+ class Result
3
+
4
+ def self.map_raw_results(raw_results)
5
+ raw_results.map { |r| new(r) }
6
+ end
7
+
8
+ def initialize(attrs)
9
+ @status = attrs["status"]
10
+ @full_name = attrs["fullName"]
11
+ @description = attrs["description"]
12
+ @failed_expectations = map_failures(attrs["failedExpectations"])
13
+ @suite_name = full_name.slice(0, full_name.size - description.size - 1)
14
+ end
15
+
16
+ def succeeded?
17
+ status == 'passed'
18
+ end
19
+
20
+ def failed?
21
+ status == 'failed'
22
+ end
23
+
24
+ def pending?
25
+ status == 'pending'
26
+ end
27
+
28
+ attr_reader :full_name, :description, :failed_expectations, :suite_name
29
+
30
+ private
31
+ attr_reader :status
32
+
33
+ def map_failures(failures)
34
+ failures.map do |e|
35
+ short_stack = if e["stack"]
36
+ e["stack"].split("\n").slice(0, 7).join("\n")
37
+ else
38
+ "No stack trace present."
39
+ end
40
+ Failure.new(e["message"], short_stack)
41
+ end
42
+ end
43
+
44
+ class Failure < Struct.new(:message, :stack); end
45
+ end
46
+ end
@@ -2,6 +2,7 @@
2
2
  <html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
3
  <head>
4
4
  <meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
5
6
  <title>Jasmine suite</title>
6
7
  <link rel="shortcut icon" type="image/png" href="/__images__/jasmine_favicon.png">
7
8
  <% css_files.each do |css_file| %>
@@ -12,7 +13,8 @@
12
13
  <% end %>
13
14
 
14
15
  </head>
15
- <body>
16
+ <!-- TODO: turbolinks breaks spec filter links -->
17
+ <body data-no-turbolink>
16
18
  <div id="jasmine_content"></div>
17
19
  </body>
18
20
  </html>
@@ -0,0 +1,54 @@
1
+ (function() {
2
+ /**
3
+ * Wait until the test condition is true or a timeout occurs. Useful for waiting
4
+ * on a server response or for a ui change (fadeIn, etc.) to occur.
5
+ *
6
+ * @param testFx javascript condition that evaluates to a boolean,
7
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
8
+ * as a callback function.
9
+ * @param onReady what to do when testFx condition is fulfilled,
10
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
11
+ * as a callback function.
12
+ */
13
+ function waitFor(testFx, onReady) {
14
+ var condition = false,
15
+ interval = setInterval(function() {
16
+ if (!condition) {
17
+ condition = (typeof(testFx) === 'string' ? eval(testFx) : testFx());
18
+ } else {
19
+ if (typeof(onReady) === 'string') {
20
+ eval(onReady);
21
+ } else {
22
+ onReady();
23
+ }
24
+ clearInterval(interval);
25
+ }
26
+ }, 100);
27
+ }
28
+
29
+ var url = phantom.args[0];
30
+ var batchSize = parseInt(phantom.args[1], 10);
31
+ var page = require('webpage').create();
32
+
33
+ page.open(url, function(status) {
34
+ if (status !== "success") {
35
+ phantom.exit(1);
36
+ } else {
37
+ waitFor(function() {
38
+ return page.evaluate(function() {
39
+ return jsApiReporter && jsApiReporter.finished
40
+ });
41
+ }, function() {
42
+ var index = 0, results;
43
+ do {
44
+ results = page.evaluate(function(index, batchSize) {
45
+ return jsApiReporter.specResults(index, batchSize)
46
+ }, index, batchSize);
47
+ console.log(JSON.stringify(results));
48
+ index += batchSize;
49
+ } while (results && results.length == batchSize)
50
+ phantom.exit(0);
51
+ });
52
+ }
53
+ });
54
+ }).call(this);
@@ -0,0 +1,29 @@
1
+ require 'phantomjs'
2
+
3
+ module Jasmine
4
+ module Runners
5
+ class PhantomJs
6
+ def initialize(formatter, jasmine_server_url, result_batch_size)
7
+ @formatter = formatter
8
+ @jasmine_server_url = jasmine_server_url
9
+ @result_batch_size = result_batch_size
10
+ end
11
+
12
+ def run
13
+ command = "#{Phantomjs.path} '#{File.join(File.dirname(__FILE__), 'phantom_jasmine_run.js')}' #{jasmine_server_url} #{result_batch_size}"
14
+ IO.popen(command) do |output|
15
+ output.each do |line|
16
+ raw_results = JSON.parse(line, :max_nesting => false)
17
+ results = raw_results.map { |r| Result.new(r) }
18
+ formatter.format(results)
19
+ end
20
+ end
21
+ formatter.done
22
+ end
23
+
24
+ private
25
+ attr_reader :formatter, :jasmine_server_url, :result_batch_size
26
+ end
27
+ end
28
+ end
29
+
@@ -1,7 +1,14 @@
1
1
  namespace :jasmine do
2
- require 'jasmine/config'
2
+ task :configure do
3
+ require 'jasmine/config'
3
4
 
4
- Jasmine.load_configuration_from_yaml
5
+ begin
6
+ Jasmine.load_configuration_from_yaml(ENV['JASMINE_CONFIG_PATH'])
7
+ rescue Jasmine::ConfigNotFound => e
8
+ puts e.message
9
+ exit 1
10
+ end
11
+ end
5
12
 
6
13
  task :require do
7
14
  require 'jasmine'
@@ -17,30 +24,44 @@ namespace :jasmine do
17
24
  end
18
25
 
19
26
  desc 'Run continuous integration tests'
20
- task :ci => %w(jasmine:require_json jasmine:require) do
21
- require 'rspec'
22
- require 'rspec/core/rake_task'
23
-
24
- RSpec::Core::RakeTask.new(:jasmine_continuous_integration_runner) do |t|
25
- t.rspec_opts = ['--colour', '--format', Jasmine.config.spec_format || 'progress']
26
- t.verbose = true
27
- if Jasmine::Dependencies.use_asset_pipeline?
28
- t.rspec_opts += ["-r #{File.expand_path(File.join(::Rails.root, 'config', 'environment'))}"]
27
+ task :ci => %w(jasmine:require_json jasmine:require jasmine:configure) do
28
+ config = Jasmine.config
29
+
30
+ server = Jasmine::Server.new(config.port(:ci), Jasmine::Application.app(config))
31
+ t = Thread.new do
32
+ begin
33
+ server.start
34
+ rescue ChildProcess::TimeoutError
29
35
  end
30
- t.pattern = [Jasmine.runner_filepath]
36
+ # # ignore bad exits
31
37
  end
38
+ t.abort_on_exception = true
39
+ Jasmine::wait_for_listener(config.port(:ci), 'jasmine server')
40
+ puts 'jasmine server started.'
41
+
42
+ formatters = config.formatters.map { |formatter_class| formatter_class.new }
43
+
44
+ exit_code_formatter = Jasmine::Formatters::ExitCode.new
45
+ formatters << exit_code_formatter
46
+
47
+ url = "#{config.host}:#{config.port(:ci)}/"
48
+ runner = config.runner.call(Jasmine::Formatters::Multi.new(formatters), url)
49
+ runner.run
32
50
 
33
- Rake::Task['jasmine_continuous_integration_runner'].invoke
51
+ exit exit_code_formatter.exit_code
34
52
  end
35
53
 
36
- task :server => 'jasmine:require' do
37
- port = Jasmine.config.jasmine_port || 8888
38
- puts 'your tests are here:'
39
- puts " http://localhost:#{port}/"
40
- app = Jasmine::Application.app(Jasmine.config)
41
- Jasmine::Server.new(port, app).start
54
+ task :server => %w(jasmine:require jasmine:configure) do
55
+ config = Jasmine.config
56
+ port = config.port(:server)
57
+ server = Jasmine::Server.new(port, Jasmine::Application.app(Jasmine.config))
58
+ puts "your server is running here: http://localhost:#{port}/"
59
+ puts "your tests are here: #{config.spec_dir}"
60
+ puts "your source files are here: #{config.src_dir}"
61
+ puts ''
62
+ server.start
42
63
  end
43
64
  end
44
65
 
45
- desc 'Run specs via server'
46
- task :jasmine => %w(jasmine:server)
66
+ desc 'Run specs via server:ci'
67
+ task :jasmine => %w(jasmine:server)