{"id":13503675,"url":"https://github.com/opal/opal-rspec","last_synced_at":"2025-07-09T05:34:51.302Z","repository":{"id":11070192,"uuid":"13413689","full_name":"opal/opal-rspec","owner":"opal","description":"Opal + RSpec = ♥️","archived":false,"fork":false,"pushed_at":"2024-02-24T06:33:49.000Z","size":1352,"stargazers_count":61,"open_issues_count":0,"forks_count":15,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-02T06:08:24.639Z","etag":null,"topics":["opal","opal-rspec","rspec","ruby"],"latest_commit_sha":null,"homepage":"https://opalrb.com/docs/guides/master/rspec.html","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-10-08T13:09:45.000Z","updated_at":"2024-08-27T08:55:40.000Z","dependencies_parsed_at":"2024-02-23T12:43:08.594Z","dependency_job_id":"13fc5de1-d5d4-4c38-9ac1-4ec9bf89b556","html_url":"https://github.com/opal/opal-rspec","commit_stats":{"total_commits":738,"total_committers":9,"mean_commits":82.0,"dds":0.6436314363143631,"last_synced_commit":"804d13d8e144f485fd173ebf7fee0bcdc9746f26"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal-rspec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal-rspec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal-rspec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal-rspec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opal","download_url":"https://codeload.github.com/opal/opal-rspec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248008630,"owners_count":21032556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["opal","opal-rspec","rspec","ruby"],"created_at":"2024-07-31T23:00:43.078Z","updated_at":"2025-04-09T09:07:57.154Z","avatar_url":"https://github.com/opal.png","language":"Ruby","readme":"# opal-rspec\n\n[![Build Status](http://img.shields.io/travis/opal/opal-rspec/master.svg?style=flat)](http://travis-ci.org/opal/opal-rspec)\n[![Quality](https://img.shields.io/codeclimate/maintainability-percentage/opal/opal-rspec.svg?style=flat)](https://codeclimate.com/github/opal/opal-rspec)\n[![Version](http://img.shields.io/gem/v/opal-rspec.svg?style=flat)](https://rubygems.org/gems/opal-rspec)\n\nAn attempt at a compatibility layer of RSpec for Opal.\n\n## Usage\n\nAdd `opal-rspec` to your Gemfile:\n\n```ruby\ngem 'opal-rspec'\n```\n\n*(since v0.7.1)*\n\nThen 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!\n\n_spec-opal/simple_sum_spec.rb_\n\n```rb\nRSpec.describe 'a simple sum' do\n  it 'equals two!' do\n    expect(1 + 1).to eq(2)\n  end\nend\n```\n\nTo run your specs, simply type:\n\n```bash\nbundle exec opal-rspec --color spec-opal/\n```\n\n## Requirements\n\nBesides what's already reflected in the GEM dependencies:\n* Browser if you want to run and debug tests that way\n\n### Run specs in Headless Chromium\n\nTo run specs, a rake task can be added which will load all spec files from\n`spec-opal/`:\n\n```ruby\nrequire 'opal/rspec/rake_task'\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\nend\n```\n\nThen, to run your specs inside headless chrome (the default runner), just run the rake task:\n\n```\nbundle exec rake\n```\n\nEnable colors in the output\n\n```\nSPEC_OPTS=\"--color\" bundle exec rake\n```\n\nUse a different formatter\n\n```\nSPEC_OPTS=\"--format json\" bundle exec rake\n```\n\nThe following formatters have been tested:\n* Default (progress)\n* Documentation\n* JSON\n\nIf you need to specify additional requires for a custom formatter, you can do this:\n\n```\nSPEC_OPTS=\"--format SomeFormatter --require some_formatter\" bundle exec rake\n```\n\nYou can also customize the pattern of specs used similiar to how RSpec's rake task works:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\n  # server is an instance of Opal::Server in case you want to add to the load path, customize, etc.\n  task.pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns\n  # NOTE: opal-rspec, like rspec, only adds 'spec' to the Opal load path unless you set default_path\n  task.default_path = 'spec_alternate'\nend\n```\n\nExcluding patterns can be setup this way:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\n\n  task.exclude_pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns\nend\n```\n\nFileLists (as in Rake FileLists) can also be supplied:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\n\n  task.files = FileList['spec/**/something_spec.rb']\nend\n```\n\nHeadless Chromium will timeout by default after 60 seconds. If you need to lengthen the timeout value, set it like this:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\n\n  task.files = FileList['spec/**/something_spec.rb']\n  task.timeout = 80000 # 80 seconds, unit needs to be milliseconds\nend\n```\n\nArity 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:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :chrome\n\n  task.arity_checking = :disabled\nend\n```\n\nIf 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.\n\n*(since v1.1.0)*\n\nYou 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.\n\n### Run specs in Node.js\n\nSame options as above, you can use the `RUNNER=node` environment variable\n(which is the default) or use the Rake task like so:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :node\nend\n```\n\n### Run specs in a browser\n\nSame options as above, you can use the `RUNNER=server` environment variable\n(which is the default) or use the Rake task like so:\n\n```ruby\nOpal::RSpec::RakeTask.new(:default) do |server, task|\n  task.runner = :server\nend\n```\n\n*(since v1.1.0)*\n\nWhile `server` value runs a server, you can here supply also respectively\n`chrome`, `firefox` or `safari` to run the test using a headless browser.\n\n### Run specs in a browser (Sprockets, deprecated)\n\n`opal-rspec` can use sprockets to build and serve specs over a simple rack\nserver. Add the following to a `config.ru` file (see config.ru in this GEM):\n\n```ruby\nrequire 'opal/rspec/sprockets'\n# or use Opal::RSpec::SprocketsEnvironment.new(spec_pattern='spec-opal/**/*_spec.{rb,opal}') to customize the pattern\nsprockets_env = Opal::RSpec::SprocketsEnvironment.new\nrun Opal::Server.new(sprockets: sprockets_env) { |s|\n  s.main = 'opal/rspec/sprockets_runner'\n  sprockets_env.add_spec_paths_to_sprockets\n  s.debug = true\n}\n```\n\nThen run the rack server `bundle exec rackup` and visit `http://localhost:9292`\nin any web browser.\n\nA new feature as of opal-rspec 0.5 allows you to click a 'Console' button in the browser's test results and get a\nclickable stack trace in the browser console. This should ease debugging with long, concatenated script files and trying\nto navigate to where an exception occurred.\n\n## Async examples\n\n`opal-rspec` adds support for async specs to rspec.\n\n```ruby\n# await: *await*\n\nrequire 'opal/rspec/async'\n\ndescribe MyClass do\n  # normal example\n  it 'does something' do\n    expect(:foo).to eq(:foo)\n  end\n\n  # async example\n  it 'does something else, too' do\n    promise = PromiseV2.new\n    delay 1 do\n      expect(:foo).to eq(:foo)\n      promise.resolve\n    end\n    promise\n  end\n\n  it 'does another thing' do\n    # Argument is number of seconds, delay_with_promise is a convenience method that will\n    # call setTimeout with the block and return a promise\n    delay_with_promise 0 do\n      expect(:foo).to eq(:foo)\n    end\n  end\nend\n\ndescribe MyClass2 do\n  # will wait for the before promise to complete before proceeding\n  before do\n    delay_with_promise 0 do\n      puts 'async before action'\n    end\n  end\n\n  # async subject works too\n  subject do\n    delay_with_promise 0 do\n      42\n    end\n  end\n\n  it { expect(subject.await).to eq 42 }\n\n  # If you use an around block and have async specs, you must use this approach\n  around do |example|\n    puts 'do stuff before'\n    example.run_await.then do\n      puts 'do stuff after example'\n    end\n  end\nend\n```\n\nAdvantages:\n\n* Assuming your subject under test (or matchers) return/use promises, or uses `await` syntax, the syntax is the same for sync or async specs\n\nLimitations:\n\n* Opal-rspec will not timeout while waiting for your async code to finish\n\nChanges since 1.0:\n\n* 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)\n* Both `let` and `subject` that return a promise (ie. are async) must be referenced with an `.await` method\n* In `around` blocks, you must call `example.run_await` instead of just `example.run`\n* 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)\n\n## Opal load path\n\nNOTE: 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.\n\n```ruby\nOpal::RSpec::RakeTask.new do |server, task|\n  task.default_path = 'spec/javascripts'\nend\n```\n\nIf you need to add additional load paths to run your specs, then use the `append_path` method like this:\n\n```ruby\nOpal::RSpec::RakeTask.new do |server, task|\n  server.append_path 'some_path'\nend\n```\n\nSince 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:\n\n```ruby\nOpal::RSpec::RakeTask.new do |server, task|\n  server.append_path 'lib'\n  task.default_path = 'spec'\n  task.files = FileList['spec/**/*_spec.rb']\nend\n```\n\n## Other Limitations/Known Issues\n\n80%+ 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.\n\n* Core Examples\n  * Example groups included like this are currently not working:\n```ruby\nmodule TestMod\n  def self.included(base)\n    base.class_eval do\n      describe 'foo' do\n      ...\n      end\n    end\n  end\nend\n\nRSpec.configure do |c|\n  c.include TestMod\nend\n```\n* Formatting/Reporting\n  * Specs will not have file path/line number information on them unless they are supplied from user metadata or they fail, see [this issue](https://github.com/opal/opal-rspec/issues/36)\n  * In Firefox w/ the browser runner, no backtraces show up with failed specs\n* Configuration\n  * Not all RSpec runner options are supported yet\n  * 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\n  * 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.\n  * Random order does not work yet due to lack of [srand/Random support](https://github.com/opal/opal/issues/639) and RSpec's bundled Random implementation, `RSpec::Core::Backports::Random`, locks the browser/Phantom. If you specify random order, it will be ignored.\n* Matchers\n  * predicate matchers (be_some_method_on_your_subject) do not currently work with delegate objects (Opal `DelegateClass` is incomplete)\n  * equal and eq matchers function largely the same right now since `==` and `equal?` in Opal are largely the same\n  * time based matching is not yet tested\n  * Due to some issues with splats and arity in Opal, respond_to matchers may not work properly on methods with splats\n* Mocks\n  * `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`\n  * 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\n  * mocking class methods (including `::new`) is currently broken\n  * `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)\n  * `object_spy` is not supported (depends on proper initializer behavior in `ObjectVerifyingDoubleMethods`)\n  * verifying partial doubles do not fully work yet (arity issues with Opal)\n  * chaining and_return after do...end does not work\n  * duck_type argument matching is still buggy\n  * RSpec's marshal support does not yet work with Opal's marshaller (so patch_marshal_to_support_partial_doubles config setting is not supported)\n\n## Contributing\n\nInstall required gems at required versions:\n\n    $ bundle install\n\nopal-rspec uses a bundled copy of rspec to fix the areas where\nopal cannot handle certain features of rspec. To build that file,\nwhich is needed to run specs, use:\n\n    $ git submodule update --init\n\nWhen 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\n\n## License\n\n(The MIT License)\n\nCopyright (C) 2022-2023 by hmdne and the Opal contributors\nCopyright (C) 2015 by Brady Wied\nCopyright (C) 2013 by Adam Beynon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopal%2Fopal-rspec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopal%2Fopal-rspec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopal%2Fopal-rspec/lists"}