jasmine 2.0.0.rc2 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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)