GithubHelp home page GithubHelp logo

opal / opal-rspec Goto Github PK

View Code? Open in Web Editor NEW
58.0 10.0 15.0 1.32 MB

Opal + RSpec = ♥️

Home Page: https://opalrb.com/docs/guides/master/rspec.html

Ruby 99.76% HTML 0.20% Opal 0.02% Shell 0.02%
opal-rspec ruby rspec opal

opal-rspec's Introduction

opal-rspec

Build Status Quality Version

An attempt at a compatibility layer of RSpec for Opal.

Usage

Add opal-rspec to your Gemfile:

gem 'opal-rspec'

(since v0.7.1)

Then type opal-rspec --init, this command will create a spec-opal/ folder for you with a minimal spec_helper.rb file. At this point you can write your first opal-spec!

spec-opal/simple_sum_spec.rb

RSpec.describe 'a simple sum' do
  it 'equals two!' do
    expect(1 + 1).to eq(2)
  end
end

To run your specs, simply type:

bundle exec opal-rspec --color spec-opal/

Requirements

Besides what's already reflected in the GEM dependencies:

  • Browser if you want to run and debug tests that way

Run specs in Headless Chromium

To run specs, a rake task can be added which will load all spec files from spec-opal/:

require 'opal/rspec/rake_task'
Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome
end

Then, to run your specs inside headless chrome (the default runner), just run the rake task:

bundle exec rake

Enable colors in the output

SPEC_OPTS="--color" bundle exec rake

Use a different formatter

SPEC_OPTS="--format json" bundle exec rake

The following formatters have been tested:

  • Default (progress)
  • Documentation
  • JSON

If you need to specify additional requires for a custom formatter, you can do this:

SPEC_OPTS="--format SomeFormatter --require some_formatter" bundle exec rake

You can also customize the pattern of specs used similiar to how RSpec's rake task works:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome
  # server is an instance of Opal::Server in case you want to add to the load path, customize, etc.
  task.pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns
  # NOTE: opal-rspec, like rspec, only adds 'spec' to the Opal load path unless you set default_path
  task.default_path = 'spec_alternate'
end

Excluding patterns can be setup this way:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome

  task.exclude_pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns
end

FileLists (as in Rake FileLists) can also be supplied:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome

  task.files = FileList['spec/**/something_spec.rb']
end

Headless Chromium will timeout by default after 60 seconds. If you need to lengthen the timeout value, set it like this:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome

  task.files = FileList['spec/**/something_spec.rb']
  task.timeout = 80000 # 80 seconds, unit needs to be milliseconds
end

Arity checking is enabled by default. Opal allows you to disable arity checking (faster in production this way) but for unit testing, you probably want information on arity mismatch. If you wish to disable it, configure your Rake task like this:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :chrome

  task.arity_checking = :disabled
end

If you don't specify a runner using task.runner, a default one is Node. In this case you can also use RUNNER=chrome to run a particular test with Headless Chromium.

(since v1.1.0)

You can also put default options into an .rspec-opal file, akin to how RSpec works. Those options will be propagated to Rake task, invocations of Opal::RSpec::Runner and also the opal-rspec command line tool.

Run specs in Node.js

Same options as above, you can use the RUNNER=node environment variable (which is the default) or use the Rake task like so:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :node
end

Run specs in a browser

Same options as above, you can use the RUNNER=server environment variable (which is the default) or use the Rake task like so:

Opal::RSpec::RakeTask.new(:default) do |server, task|
  task.runner = :server
end

(since v1.1.0)

While server value runs a server, you can here supply also respectively chrome, firefox or safari to run the test using a headless browser.

Run specs in a browser (Sprockets, deprecated)

opal-rspec can use sprockets to build and serve specs over a simple rack server. Add the following to a config.ru file (see config.ru in this GEM):

require 'opal/rspec/sprockets'
# or use Opal::RSpec::SprocketsEnvironment.new(spec_pattern='spec-opal/**/*_spec.{rb,opal}') to customize the pattern
sprockets_env = Opal::RSpec::SprocketsEnvironment.new
run Opal::Server.new(sprockets: sprockets_env) { |s|
  s.main = 'opal/rspec/sprockets_runner'
  sprockets_env.add_spec_paths_to_sprockets
  s.debug = true
}

Then run the rack server bundle exec rackup and visit http://localhost:9292 in any web browser.

A new feature as of opal-rspec 0.5 allows you to click a 'Console' button in the browser's test results and get a clickable stack trace in the browser console. This should ease debugging with long, concatenated script files and trying to navigate to where an exception occurred.

Async examples

opal-rspec adds support for async specs to rspec.

# await: *await*

require 'opal/rspec/async'

describe MyClass do
  # normal example
  it 'does something' do
    expect(:foo).to eq(:foo)
  end

  # async example
  it 'does something else, too' do
    promise = PromiseV2.new
    delay 1 do
      expect(:foo).to eq(:foo)
      promise.resolve
    end
    promise
  end

  it 'does another thing' do
    # Argument is number of seconds, delay_with_promise is a convenience method that will
    # call setTimeout with the block and return a promise
    delay_with_promise 0 do
      expect(:foo).to eq(:foo)
    end
  end
end

describe MyClass2 do
  # will wait for the before promise to complete before proceeding
  before do
    delay_with_promise 0 do
      puts 'async before action'
    end
  end

  # async subject works too
  subject do
    delay_with_promise 0 do
      42
    end
  end

  it { expect(subject.await).to eq 42 }

  # If you use an around block and have async specs, you must use this approach
  around do |example|
    puts 'do stuff before'
    example.run_await.then do
      puts 'do stuff after example'
    end
  end
end

Advantages:

  • Assuming your subject under test (or matchers) return/use promises, or uses await syntax, the syntax is the same for sync or async specs

Limitations:

  • Opal-rspec will not timeout while waiting for your async code to finish

Changes since 1.0:

  • If you use async features, it's crucial to use a # await: *await* magic comment (this will cause any call to a method containing an await word to be compiled with an await ES8 keyword)
  • Both let and subject that return a promise (ie. are async) must be referenced with an .await method
  • In around blocks, you must call example.run_await instead of just example.run
  • Only PromiseV2 is supported (PromiseV1 may work, but you should migrate your application to use PromiseV2 nevertheless, in Opal 2.0 it will become the default)

Opal load path

NOTE: Only the 'spec' directory will be added to the Opal load path by default. Use the Rake task's default_path setting to change that. Here's an example of that.

Opal::RSpec::RakeTask.new do |server, task|
  task.default_path = 'spec/javascripts'
end

If you need to add additional load paths to run your specs, then use the append_path method like this:

Opal::RSpec::RakeTask.new do |server, task|
  server.append_path 'some_path'
end

Since 0.8, the default spec location is spec-opal and the default source location is lib-opal. If your code aims to run the same specs and libraries for Ruby and Opal, you should use the following:

Opal::RSpec::RakeTask.new do |server, task|
  server.append_path 'lib'
  task.default_path = 'spec'
  task.files = FileList['spec/**/*_spec.rb']
end

Other Limitations/Known Issues

80%+ of the RSpec test suites pass so most items work but there are a few things that do not yet work. Do note that some of the items described here may actually work in the recent version.

  • Core Examples
    • Example groups included like this are currently not working:
module TestMod
  def self.included(base)
    base.class_eval do
      describe 'foo' do
      ...
      end
    end
  end
end

RSpec.configure do |c|
  c.include TestMod
end
  • Formatting/Reporting
    • Specs will not have file path/line number information on them unless they are supplied from user metadata or they fail, see this issue
    • In Firefox w/ the browser runner, no backtraces show up with failed specs
  • Configuration
    • Not all RSpec runner options are supported yet
    • At some point, using node + Phantom's ability to read environment variables could be combined with a opal friendly optparse implementation to allow full options to be supplied/parsed
    • Expect and should syntax are both enabled. They cannot be disabled due to past bugs with the undef keyword in Opal. Status of changing this via config has not been retested.
    • Random order does not work yet due to lack of srand/Random support and RSpec's bundled Random implementation, RSpec::Core::Backports::Random, locks the browser/Phantom. If you specify random order, it will be ignored.
  • Matchers
    • predicate matchers (be_some_method_on_your_subject) do not currently work with delegate objects (Opal DelegateClass is incomplete)
    • equal and eq matchers function largely the same right now since == and equal? in Opal are largely the same
    • time based matching is not yet tested
    • Due to some issues with splats and arity in Opal, respond_to matchers may not work properly on methods with splats
  • Mocks
    • allow_any_instance/any_instance_of/any_instance are unstable and may cause runner to crash due to issues with redefining the === operator, which breaks a case statement inside Hooks#find_hook
    • using expect/allow on String, Number, or any immutable bridged/native class, does not work since rspec-mocks uses singleton classes and those cannot be defined on immutable objects
    • mocking class methods (including ::new) is currently broken
    • class_double/class_spy are not supported (it depends on ClassVerifyingDouble inheriting from Module to support transferring nested constants, but that doesn't work on Opal)
    • object_spy is not supported (depends on proper initializer behavior in ObjectVerifyingDoubleMethods)
    • verifying partial doubles do not fully work yet (arity issues with Opal)
    • chaining and_return after do...end does not work
    • duck_type argument matching is still buggy
    • RSpec's marshal support does not yet work with Opal's marshaller (so patch_marshal_to_support_partial_doubles config setting is not supported)

Contributing

Install required gems at required versions:

$ bundle install

opal-rspec uses a bundled copy of rspec to fix the areas where opal cannot handle certain features of rspec. To build that file, which is needed to run specs, use:

$ git submodule update --init

When updating the RSpec versions, after updating the submodule revisions, you may need to use the generate_requires Rake task in order to pre-resolve RSpec's dynamic requires

License

(The MIT License)

Copyright (C) 2022-2023 by hmdne and the Opal contributors Copyright (C) 2015 by Brady Wied Copyright (C) 2013 by Adam Beynon

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

opal-rspec's People

Contributors

adambeynon avatar aostrega avatar elia avatar hmdne avatar iliabylich avatar meh avatar wied03 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opal-rspec's Issues

async examples

RSpec would make it very difficult for us to have "native" async examples as the runners run all examples sync. So, if we introduce ExampleGroup#async, then we can hijack these examples and run them ourselves. They would not be examples as such, but we can run them async in our own runner:

describe "Group" do
  it "foo" { }
  it "bar" {}
  async "baz" { }
end

RSpec.world.all_examples
# => ["Group foo", "Group bar"]

OpalRSpec.async_examples
# => ["Group baz"]

We can then run all normal rspec examples directly through rspec, but then run all async examples last in an async manner. All before/after parts can run just as normal.

Performance Improvement Ideas

A lot of time gets spent loading the example groups and examples that will be tested.

  1. Precompilation/minification
  2. Closure compilation?
  3. Other profiling
  4. When specific examples are focused on, see if they can be filtered out BEFORE opal compilation
  5. Per #36 and #57, reduce the exception throwing just to get stack traces

Can't build

I'm trying to run the rake task to build and it produces the following:

$ bundle exec rake build

Your Gemfile lists the gem rake (>= 0) more than once.
You should probably keep only one of them.
While it's not a problem now, it could cause errors if you change the version of just one of them later.
Cannot handle dynamic require :rspec/core/configuration:
Cannot handle dynamic require :rspec/core/configuration:533
Cannot handle dynamic require :rspec/core/configuration:857
Cannot handle dynamic require :rspec/core/configuration:1095
Cannot handle dynamic require :rspec/core/configuration:1095
Cannot handle dynamic require :rspec/core:
Cannot handle dynamic require :rspec/core:200
Cannot handle dynamic require :rspec/core:200

Sprockets

Deal with sprockets separation from Opal core

Opal 0.9 Compatibility Issue

Known issue with Opal 0.9 final. 0.9.beta1 worked in our tests but something has broken since then:

  • 0.9.beta01
  • 0.9.beta02
  • 0.9.rc01
  • 0.9.1 - Will not work on 0.9.0 due to the bug mentioned below. Does now pass against opal 0.9 stable since the bug has been fixed there. Will be able to check this off once 0.9.1 is released.
  • Close this issue once Travis passes with 0.9.1

Compiler/Line Number Metadata

Add an optional compiler helper that will add_special call nodes for describe, context, it, etc.

The modified code will still call describe, call, etc. but it will add a caller metadata attribute in implicitly to the arguments list. Caller should be an array with 1 element containing the filename and line number of the spec.

Will need to handle cases where:

  • User has already supplied the caller
  • Existing metadata being passed as a hash variable
  • Existing metadata passed with { }
  • Existing metadata passed with an implicit hash
  • No metadata being passed
  • No arguments at all (not sure if describe;do;end is valid)

It should be bootstrap compatible and configurable as to when this runs, some ideas:

  • Only files ending in _spec.rb
  • Use a compiler setting (we do have access to the compiler object in the call node, we can add an additional setting)
  • Opt in (need to require the compiler patch, this one is not mutually exclusive)

Testing:

  • Unit test with MRI - see note below
  • Unit test with bootstrap/Opal compilation
  • Maybe include in RSpec's specs so they can find location? It might be too difficult to test this so it might be easier to just have a separate integration test

Compiler test, the compiled version with the patch on:

describe 'foo' do
end

should equal this with the patch off:

describe 'foo', caller: ['/some/file/path.rb:123'] do
end

how to require gem or a source file ?

I am testing a gem (react.rb) and in the tests I want to use opal-jquery

simply putting require 'opal-jquery' in the spec_helper.rb does not work (I have tried many combinations) and yes the opal-jquery gem is listed as a development dependency.

Likewise I want to put the sources for react.js in the gem, and then pull them in, during rspec testing, but again it doesn't want to work.

So if I have a file: lib/sources/react_v13.js, I assume that I can pull this in doing:
require 'reactive-ruby/sources/react_v13'

The error I get is like this:

Sprockets::FileNotFound: couldn't find file 'opal-jquery' with type 'application/javascript'

Thanks in advance

Travis errors out with CRuby v1.9.3

It errors because of a too new version of rack that only supports
Ruby >= 2.0.m, it's probably just
a matter of tweaking the test stuff that's present in the Gemfile.

I disabled 1.9.3 in bb666f3 but should be fixed and re-enabled soon.

support for stubbing?

Does opal-rspec not support stubbing? When I try with this code:

      Wedge::Plugins::Uploader.any_instance.stub(:settings).and_return({
        aws_access_key_id: 123456,
        bucket: 'wedge'
      })

I get this error: #<< not supported. Mutable String methods are not supported in Opal.

Opal Master / 0.10 Compatibility

Work is on the bugs/arity_check branch:

Rake Tasks:

  • other_specs
  • opal_specs
  • rspec-core
  • rspec-support
  • Figure out why Opal 0.9 Travis builds are failing in arity checking branch - shouldn't be since arity checking is only enabled for >= 0.10
  • rspec-expectations - filtered more respond_to problems and stopped backtrace/undef/rspec core case from running
  • rspec-mocks
  • complete CI run
  • Merge code into master - awaiting @elia and #56 :)
  • Close issue and submit opal PR that modifies the build process. It should checkout a tag of opal-rspec and run its specs in order to provide another "test" to augment the opal specs.

Can't start Rails 4.2.3 app with latest opal-rspec

I wanted to try out Opal 0.9 beta2 in a new Rails app I recently started, so I switched to the latest GitHub version of opal, opal-rails, opal-jquery, and opal-rspec in my Gemfile, and now I'm getting this error trying to start Rails server:

/Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec/pre_rack_locator.rb:4:in `require_relative': cannot load such file -- /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/rspec-core/lib/rspec/core/ruby_project (LoadError)
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec/pre_rack_locator.rb:4:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec/sprockets_environment.rb:4:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec/sprockets_environment.rb:4:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec.rb:3:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal/rspec.rb:3:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal-rspec.rb:1:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rspec-a3b7139b29b6/lib/opal-rspec.rb:1:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rails-9f2557531dae/lib/opal/rails.rb:4:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rails-9f2557531dae/lib/opal/rails.rb:4:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rails-9f2557531dae/lib/opal-rails.rb:1:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/bundler/gems/opal-rails-9f2557531dae/lib/opal-rails.rb:1:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:76:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:72:in `each'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:72:in `block in require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:61:in `each'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler/runtime.rb:61:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.5/lib/bundler.rb:134:in `require'
    from /Users/jwhite/RailsApps/mariposta4/config/application.rb:16:in `<top (required)>'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:78:in `require'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:78:in `block in server'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:75:in `tap'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:75:in `server'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/jwhite/.rvm/gems/ruby-2.2.1@rails42/gems/railties-4.2.3/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:8:in `require'
    from bin/rails:8:in `<main>'

Investigate Using RSpec's Specs

Instead of the current Rake task setup, consider using RSpec's specs (and overriding the run_command approach they use). Then only the opal-rspec specific specs to maintain are the async ones.

Example will not run

~/code/clones/opal-rspec/example $ bundle exec rake
Error: Sprockets::FileNotFound: couldn't find file 'opal/rspec/rspec'
  (in /home/artur/code/clones/opal-rspec/opal/opal/rspec.rb)

  http://localhost:9999/assets/opal/rspec/sprockets_runner.js:1

Can't require or see files outside of spec/

Im trying to run a test but it can't see the file under opal/ (im creating a test suite on a gem)
im requiring the file path on opal like this:

require 'opal'

Opal.append_path File.expand_path('../../opal', __FILE__)

requiring files directly doesn't work either, not even requiring it with expand path, probably im missing something but i can't make it work :(

Async specs shortcomings

Async specs need some fixing, a common error sprouting up is this.

It obviously doesn't make any sense, so it's either coming from something using run_async out of context, or dunno.

There's to consider I named both methods async, I assumed AsyncDefinitions and AsyncHelpers were never going to collide. Is this really the case?

Other than that the formatting of async specs needs some fixing, especially regarding where/how it's formatted.

Right now it just gets mixed in with other example groups, and it's really misleading.

Add option to rake task for --backtrace

Due to the nature of my program, I end up using a lot of pack and unpack calls, which I have to provide polyfills for, and native JavaScript. Therefore, I end up getting a lot of exceptions because my polyfills are broken (or more likely, they use features Opal doesn't provide), and it would be very helpful to be able to see the full backtrace so I can debug more effectively. I generally always want that anyway.

If this option is already provided and I've just missed it (which is possible), maybe some additional documentation would be helpful.

RSpec 3.4 Support

Tasks:

  • - requires update
  • - sanity check fixes: core
  • - sanity check fixes: expectations
  • - sanity check fixes: matchers
  • - sanity check fixes: support
  • - sanity check fixes: mocks
  • - other_specs run properly
    • - browser
    • - Rake
  • - With an intentional failure of other_specs:
    • - browser run
    • - Rake task run
  • - async basics
  • - git submodule update
  • - opal_specs
    • - Browser runs
    • - memoization problem - fixed with configure_example workaround
    • - runs in Phantom without hanging - still hanging and missing 1 failure
    • - all pass
  • - rspec support
    • - runs in Phantom without hanging
    • - passes - only pending item was opal/opal#1449, which stops AllExceptionsExceptOnesWeMustNotRescue case compare from working
  • - rspec core
    • - compile
    • - example run blocked by shared example/class issue - opal/opal#1476
    • - uninitialized constant RSpec::Mocks::MarshalExtension::Marshal
    • - examples run
    • - correct ones pass - most example group specs pass, not getting success/fail counts with full suite. pure rspec run has 1,891 examples
  • - rspec expectations (check rspec quantity)
  • - rspec mocks (check rspec quantity)
  • - Implement 'better_async' branch changes (might be easier to make around hooks work properly with async with 3.4). Need to understand why the 'result block' is actually happening though.
  • - Verify which README limitations still apply
  • - Require 0.10.2 in Gemspec (module inheritance bug)

Results Reporting Sync/Async

Even though opal-rspec is async enabled, it seems like results often don't appear until all the tests have run.

Spring Support

(moved from opal/opal-rails#69 since spring need not be rails-specific)

Once all of the work going on with opal-rspec 0.5 is complete, it might be useful to integrate spring support in. That way the Rake task can start up and the Rack process can stay loaded, allowing quick re-runs of specs using the Rake task.

Drop Opal 0.8 support for next opal-rspec release

  • Create a 0.5 stable branch for 0.5 bugfixes
  • In master, update gemspec to require Opal 0.9
  • Remove 0.8 stable Travis build
  • Remove all compatibility checks/monkey patches for things fixed in 0.9
  • Remove opal master build from 0.9 stable travis config

version 0.3 seems incompatible with jquery v 0.2.0

I have the following gems
Using opal-jquery 0.2.0
Using opal-rspec 0.3.0.beta3

if I require 'opal-jquery' in a spec file it throws an error because the class Element base class does not match the previously defined value. (its weird because its throwing this when Element is being defined in element.js, so its as if somehow opal-rspec is defining it already???)

I can't upgrade to the next version of opal-jquery because then source maps breaks.

Let me know what I might do, fix patch to get out of this.

should_receive cause mutable string error

I get this

NotImplementedError:
       #<< not supported. Mutable String methods are not supported in Opal.

when using should_receive and any_instance. Switching allow/expec(blah).to receive works though for should_receive

stub_const doesn't work quite the same in opal 0.9

I am not 100% sure this is an opal-rspec, opal issue, or even an issue, but it used to work in Opal 0.8, but now in Opal 0.9 with latest rspec it fails:

  it "can add class names by the haml .class notation" do
    stub_const 'TestMod123::Bar', Class.new(React::Component::Base)
    TestMod123::Bar.class_eval do
      collect_other_params_as :attributes
      def render
        "a man walks into a bar".span(attributes)
      end
    end
    stub_const 'Foo', Class.new(React::Component::Base)
    Foo.class_eval do
      def render
        TestMod123::Bar().the_class
      end
    end

    expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<span class="the-class">a man walks into a bar</span>')
  end

The problem is that React::Component::Base wants to find its parent name if it is defined, so that the method "Bar()" can be defined in the parent module (TestMod123). putting some traces in the code shows that in 0.9 with latest opal-rspec, React::Component.included is being called BEFORE the name of the class is set. It does get set, but only after the class is created.

Race condition in rake task

The code in lib/opal/rspec/rake_task.rb has a race condition in the following area:

          server = fork do
            app = Opal::Server.new { |s|
              s.main = 'opal/rspec/sprockets_runner'
              s.append_path 'spec'
              s.debug = false

              block.call s if block
            }

            Rack::Server.start(:app => app, :Port => PORT, :AccessLog => [],
              :Logger => WEBrick::Log.new("/dev/null"))
          end

          system "phantomjs #{RUNNER} \"#{URL}\""
          success = $?.success?

          Process.kill(:SIGINT, server)
          Process.wait

phantomjs can attempt to run before the Rack::Server object is ready to serve, and as a result phantomjs fails, Rack gets a SIGINT in an unfortunate place, and no tests are run. I get the following traceback in this case:

vauxhall no % rake --trace opal:rspec
** Invoke opal:rspec (first_time)
** Execute opal:rspec
Cannot load: http://localhost:9999/
/usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `const_get': can't be called from trap context (ThreadError)
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `block in get'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `each'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `inject'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `get'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:38:in `block in pick'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `each'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `pick'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:57:in `default'
    from /usr/lib/ruby/vendor_ruby/rack/server.rb:268:in `server'
    from /usr/lib/ruby/vendor_ruby/rack/server.rb:257:in `block in start'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `call'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `block (2 levels) in contains_requirable_file?'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `each'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `any?'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `block in contains_requirable_file?'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `each'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `any?'
    from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `contains_requirable_file?'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:915:in `block in find_by_path'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:883:in `block in each'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:882:in `each'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:882:in `each'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:914:in `find'
    from /usr/lib/ruby/2.1.0/rubygems/specification.rb:914:in `find_by_path'
    from /usr/lib/ruby/2.1.0/rubygems.rb:188:in `try_activate'
    from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:132:in `rescue in require'
    from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:144:in `require'
    from /usr/lib/ruby/vendor_ruby/rack/handler/thin.rb:1:in `<top (required)>'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `const_get'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `block in get'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `each'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `inject'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `get'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:38:in `block in pick'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `each'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `pick'
    from /usr/lib/ruby/vendor_ruby/rack/handler.rb:57:in `default'
    from /usr/lib/ruby/vendor_ruby/rack/server.rb:268:in `server'
    from /usr/lib/ruby/vendor_ruby/rack/server.rb:264:in `start'
    from /usr/lib/ruby/vendor_ruby/rack/server.rb:141:in `start'
    from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:27:in `block (2 levels) in initialize'
    from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:18:in `fork'
    from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:18:in `block in initialize'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:240:in `call'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:240:in `block in execute'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `each'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `execute'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:179:in `block in invoke_with_call_chain'
    from /usr/lib/ruby/2.1.0/monitor.rb:211:in `mon_synchronize'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:172:in `invoke_with_call_chain'
    from /usr/lib/ruby/vendor_ruby/rake/task.rb:165:in `invoke'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:150:in `invoke_task'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `block (2 levels) in top_level'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `each'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `block in top_level'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:115:in `run_with_threads'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:100:in `top_level'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:78:in `block in run'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:176:in `standard_exception_handling'
    from /usr/lib/ruby/vendor_ruby/rake/application.rb:75:in `run'
    from /usr/bin/rake:27:in `<main>'

Inserting a sleep 2 after the fork block makes it work correctly.

Timeouts for async examples

Async examples should be limited to a timeout period.

describe "Some async tests" do
  timeout 0.4

  async "should respond correctly" do
    # ...
  end

  async "this might take a little longer", timeout: 1.0 do
    # ...
  end
end

Investigate using Promises for async specs

Instead of:

async 'HTTP requests should work' do
  HTTP.get('/users/1.json') do |res|
    run_async {
      expect(res).to be_ok
    }
  end
end

We could use:

async 'HTTP requests should work' do
  HTTP.get('/users/1.json').then do |res|
      expect(res).to be_ok
  end
end

Basically, if the example block returns a Promise, then instead of the inner run_async block, the spec runner can just wait on the Promise to resolve or reject, and then handle it accordingly.

0.5.0.beta1 does not run in Firefox/Webkit

When trying to run any spec, the following browsers/engines work (not exhaustive list):

  • Chrome
  • PhantomJS

The following do NOT:

  • Firefox
  • Headless webkit engine (using Capybara)

The latter 2 fail with a variant of this error when parsing RSpec code:

RuntimeError: Don't know how to parse $populate@http://127.0.0.1:42500/assets/rspec/core/metadata.self.js?body=1:102:47

Remove splat workarounds for Opal 0.9 targeted branch

When there is a branch that targets Opal 0.9, the splat code in fixes/reporter.rb can be removed since the pertinent part of opal/opal#858 looks to be fixed. Specifically the # without this comment and the notifications= line

class RSpec::Core::Reporter
  # https://github.com/opal/opal/issues/858
  # The problem is not directly related to the Reporter class (it has more to do with Formatter's call in add using a splat in the args list and right now, Opal does not run a to_a on a splat before the callee method takes over)
  def register_listener(listener, *notifications)
    # Without this, we won't flatten out each notification properly (e.g. example_started, finished, etc.)
    notifications = notifications[0].to_a unless notifications[0].is_a? Array    
    notifications.each do |notification|
      @listeners[notification.to_sym] << listener
    end
    true
  end
end

Simplified browser formatter

@adambeynon could you quickly come up with a very simple, no fancy graphics browser formatter?

The ChromeDriver has some issues with the generated HTML, probably because it uses retarded tags or god knows what.

Something very simple easy to interact with Selenium, actually, if you could just list the failures and ignore the ones that pass.

All I need is the summary the current formatter gives, so number of examples, number of failures, time spent testing.

And then a simple list of failures, possibly in usable HTML, so nest the describes and the its properly.

This will make running the specs on browserstack simpler, and actually make it work on Chrome. I reported the issue on the chromedriver tracker, but god knows when they'll fix it and when browserstack will start using that version.

Thanks.

Get working with arity checking enabled

  1. Code Changes
    • private_class_method needs to support multiple args - opal/opal#1168
    • All Promise::value calls without arguments need to be replaced
    • The module_exec method declaration needs to accept arguments besides a block (in Opal master the other arguments are passed on via JS arguments, but it's not in the method declaration, so the arity check fails - opal/opal#1169
    • Support fuzzy matcher filter (exclude passing)
  2. Rake Tasks:
    • other_specs
    • opal_specs
    • rspec-core - 14 unexpected failures
    • rspec-support
    • rspec-expectations
    • rspec-mocks
    • complete CI run
    • Document

Event Handlers still exists on spec completion

Testing methods that trigger events on Document, causes other specs (of other class) to fail. Maybe should clear DOM after every test?

I have to manually add an after block

after do
  Document.off :event_name
end

Phantom / window.postMessage

Not sure of the details yet but some tests that involve window.postMessage in order to test window.addEventListener seem to lock up the spec_runner code when using Phantom

fix warnings

I'll create a pull request for it at some point this week.

Remove Kernel#caller patches

Karma-opal-rspec is now using stacktrace.js:

This issue should now:

  • Remove the Kernel#caller override in opal-rspec and just put in pure, raw JS stack traces only when a test fails and point people elsewhere (wherever this github issue gets done) to use source maps. Better yet, don't include any location info to avoid the overhead (see next bullet)
  • #57 might be a more performant way of gathering metadata for every test

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.