{"id":15240477,"url":"https://github.com/selleo/rspec-tapas","last_synced_at":"2025-10-03T16:20:32.249Z","repository":{"id":32643921,"uuid":"138723624","full_name":"Selleo/rspec-tapas","owner":"Selleo","description":"Small extensions facilitating rSpec testing ","archived":false,"fork":false,"pushed_at":"2023-03-16T22:08:52.000Z","size":53,"stargazers_count":6,"open_issues_count":8,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-19T14:02:00.198Z","etag":null,"topics":["rails","rspec","rspec-capybara","rspec-matchers","ruby"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Selleo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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":"2018-06-26T10:40:06.000Z","updated_at":"2023-04-13T15:01:36.000Z","dependencies_parsed_at":"2025-02-17T10:41:39.249Z","dependency_job_id":null,"html_url":"https://github.com/Selleo/rspec-tapas","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/Selleo/rspec-tapas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Selleo%2Frspec-tapas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Selleo%2Frspec-tapas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Selleo%2Frspec-tapas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Selleo%2Frspec-tapas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Selleo","download_url":"https://codeload.github.com/Selleo/rspec-tapas/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Selleo%2Frspec-tapas/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275069608,"owners_count":25400109,"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","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["rails","rspec","rspec-capybara","rspec-matchers","ruby"],"created_at":"2024-09-29T11:05:11.542Z","updated_at":"2025-10-03T16:20:32.155Z","avatar_url":"https://github.com/Selleo.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rspec-tapas\n\nrspec-tapas is a set of small helpers and extensions we often use in [Selleo](https://selleo.com/) when testing our ruby apps.\n\n## Installation\n\nTo install rspec-tapas just add following line to your `Gemfile`s `:test` group\n\n```ruby\ngem 'rspec-tapas'\n```\n\nthen just `bundle install` and require it in `rails_helper.rb`\n\n```ruby\nrequire 'rspec_tapas/all'\n```\n\n## Helpers\n\n### StubEnv\n\n`StubEnv` is an extension that allows you to quickly stub values that should be retrieved from `ENV`.\nIt is assumed here, that you will use `fetch` method to retrieve such value (so it yields an exception when given ENV is not defined what sounds like a reasonable default).\n\n*Example*\n\n```ruby\nit 'sends a notification after checkout' do\n    stub_env('CHECKOUT_TIME', '13:00')\n    #...\nend\n```\n\nTo include this extension only, call `require rspec_tapas/stub_env`\n\n`StubEnv` is accessible in all types of specs\n\n### DateHelpers\n\n`DateHelpers` is a set of two methods that facilitate using `ActiveSupport::Testing::TimeHelpers`. Therefore you need to include `ActiveSupport::Testing::TimeHelpers` in your config if you want to use `DateHelpers`. It is as simple as\n\n```ruby\nRSpec.configure do |config|\n  config.include ActiveSupport::Testing::TimeHelpers\nend\n```\n\n#### at_date\n\n`at_date` runs contents of the block at given date, provided in a format acceptable by `Date.new`. It is basically a shortcut to `travel_to(Date.new(*args)){}`.\n\n*Example*\n\n```ruby\ncontext 'one day before deadline' do\n    it 'sends a reminder' do\n        #...\n        at_date(2018, 1, 12) do\n            SendPendingReminders.call\n        end\n        #...\n    end\nend\n```\n\n#### freeze_time\n\n`freeze_time` freezes the time and runs contents of the block at. It is basically a shortcut to `travel_to(Time.current){}`.\n\n*Example*\n\n```ruby\nit 'discards records created at the same time' do\n    #...\n    freeze_time do\n      user_1 = create(:user)\n      user_2 = create(:user)\n    end\n    #...\nend\n```\n\nTo include this extension only, call `require rspec_tapas/date_helpers`\n\n`DateHelpers` are accessible in all types of specs\n\n### ViewPage\n\n`ViewPage` is a small helper that allows testing views using capybara helpers, usually limited only to feature specs.\n\n*Example*\n\n```ruby\nRSpec.describe 'users/show.html.erb', type: :view do\n  it 'renders user name' do\n    user = create(:user, name: \"Tony\")\n    allow(view).to receive(:user) { user }\n\n    render\n\n    expect(page).to have_content(\"Tony\")\n  end\nend\n```\n\nTo include this extension only, call `require rspec_tapas/view_page`\n\n`ViewPage` is accessible only in view specs\n\n\n### InvokeTask\n\n`InvokeTask` is a small helper that facilitates calling rake tasks when testing them.\n\n*Example*\n\n```ruby\nRSpec.describe 'db:materialize', type: :rake do\n  it 'materializes db view by name' do\n    database = double(:database)\n    allow(Scenic).to receive(:database) { database }\n    allow(database).to receive(:refresh_materialized_view)\n\n    invoke_task('db:materialize', view_name: 'sample_view')\n\n    expect(database).to \\\n      have_received(:refresh_materialized_view).with('sample_view')\n  end\nend\n```\n\nTo include this extension only, call `require rspec_tapas/invoke_task`\n\n`InvokeTask` is accessible only in rake specs\n\n\n### GetMessagePart\n\n`GetMessagePart` is a set of helpers to facilitate extraction of html/plain parts of emails sent. To extract plaintext part from email, use `text_part(mail)`. To extract HTML part, use `html_part(mail)`.\n\n```ruby\nRSpec.describe ReportMailer, type: :mailer do\n  describe '#summary' do\n    it 'creates email containing orders summary' do\n      create_list(:order, 2)\n      mail = ReportMailer.summary\n\n      expect(mail.subject).to eq('Orders summary')\n      expect(html_part(mail)).to include_html(\n        \u003c\u003c~HTML\n            \u003ch1\u003eOrders summary\u003c/h1\u003e\n            \u003cstrong\u003eTotal orders created:\u003c/strong\u003e 2 \u003cbr /\u003e\n        HTML\n      )\n      expect(text_part(mail)).to include('Total orders created: 2')\n    end\n  end\nend\n```\n\nTo include this extension only, call `require rspec_tapas/get_message_part`\n\n`GetMessagePart` is accessible only in mailer specs\n\n### JsonResponse\n\n`JsonResponse` is a simple helper that transforms JSON encoded response body to `HashWithIndifferentAccess` or an array of those. This is to facilitate using regular matchers to assert such response.\n\n*Example*\n\n```ruby\nit 'returns user names and emails' do\n  create(:user, name: 'Tony', email: 'tony@stark.dev')\n  create(:user, name: 'Bruce', email: 'bruce@wayne.dev')\n\n  get '/v1/users'\n\n  expect(json_response).to match(\n    data: [\n      { name: 'Tony', email: 'tony@stark.dev' },\n      { name: 'Bruce', email: 'bruce@wayne.dev' },\n    ]\n  )\nend\n```\n\nTo include this extension only, call `require rspec_tapas/json_response`\n\n`JsonResponse` is accessible only in request and controller specs\n\n### DownloadsHelpers\n\n`DownloadsHelpers` is a set of two helpers oriented on facilitating testing downloads. First, we need to allow downloading file in given feature spec by calling `allow_file_downloads(page)`. Then, to get downloaded file contents, we need to use `downloaded_file_contents(file_name)` helper.\n\nTo allow downloads with headless-chrome capybara driver, we need to configure it in specific way. See example below:\n\n```ruby\nrequire 'selenium/webdriver'\n\nCapybara.register_driver :headless_chrome do |app|\n  options = Selenium::WebDriver::Chrome::Options.new\n  options.add_argument('--headless')\n  options.add_argument('--no-sandbox')\n  options.add_argument('--disable-gpu')\n  options.add_argument('--disable-popup-blocking')\n  options.add_argument('--window-size=1920,1200')\n  options.add_preference(\n    :download,\n    directory_upgrade: true,\n    prompt_for_download: false,\n    default_directory: RspecExtensions::DownloadsHelpers::DOWNLOADS_PATH\n  )\n  options.add_preference(:browser, set_download_behavior: { behavior: 'allow' })\n\n  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)\nend\n\nCapybara.javascript_driver = :headless_chrome\n```\n\nThen, testing downloads is just a matter of few lines of code.\n\n*Example*\n\n```ruby\nallow_file_downloads(page)\n\nclick_on 'Download report'\n\nexpect(downloaded_file_contents('daily_report.csv')).to eq(\"Name, Total revenue\\nBatman suits, 1000\")\n```\n\nTo include this extension only, call `require rspec_tapas/downloads_helpers`\n\n`DownloadsHelpers` are accessible only in feature specs\n\n### FeatureHelpers\n\n`FeatureHelpers` module contains a couple of methods useful in features specs.\n\n- `display_logs` will display browser logs in console. This is useful for debugging javascript errors in feature specs.\n- `ss` is a shortcut for `page.save_and_open_screenshot`\n- `reload_page` is a handy shortcut for reloading current page.\n\nTo include this extension only, call `require rspec_tapas/feature_helpers`\n\n`FeatureHelpers` are accessible only in feature specs\n\n### BehaviorDSL\n\n`BehaviorDSL` module has two roles. First one is to add some syntactic sugar to feature specs, by introducing additional level of describing context, but without interrupting test. This way you can group actions and assertions in readable blocks.\n\nSecond role of `BehaviorDSL` is to add capability of asserting feature - controller integration. This way we can ensure, that given block of capybara interactions were using particular controller action.\n\n*Example*\n\n```ruby\nRSpec.describe 'Users management' do\n  scenario do\n    behavior 'Admin browses existing users', using: 'Admin::UsersController#index' do\n      create(:user, name: 'Luke Cage')\n      create(:unit, name: 'Jessica Jones')\n\n      visit '/admin/users'\n\n      expect(page).to have_row_content('Full name' =\u003e 'Luke Cage')\n      expect(page).to have_row_content('Full name' =\u003e 'Jessica Jones')\n    end\n\n    behavior 'Admin updates existing user' do\n      #...\n    end\n  end\nend\n```\n\nTo include this extension only, call `require rspec_tapas/behavior_dsl`\n\n`BehaviorDSL` is accessible only in feature specs\n\n## Matchers\n\n### have_table_row\n\n`have_table_row` is a matcher dedicated to finding table rows by their values correlated with specific headers. As so, this is mostly useful in feature specs.\n\n*Examples*\n\n```ruby\n# Asserting headers by their names\nexpect(page).to have_table_row('First name' =\u003e 'Tony', 'Last name' =\u003e 'Stark', 'Rating' =\u003e 4.5)\n\n# Asserting headers by their indices\nexpect(page).to have_table_row(1 =\u003e 'Tony', 2 =\u003e 'Stark', 3 =\u003e 4.5)\n\n# Asserting headers by their indices - shorter version\nexpect(page).to have_table_row('Tony', 'Stark', 4.5)\n\n# Composing matchers\nexpect(page).to have_table_row(have_content('ny'), 'Stark')\n```\n\nTo include this matcher use: `config.include RSpecTapas::Matchers`\n\n## About Selleo\n\n![selleo](https://raw.githubusercontent.com/Selleo/selleo-resources/master/public/github_footer.png)\n\nSoftware development teams with an entrepreneurial sense of ownership at their core delivering great digital products and building culture people want to belong to. We are a community of engaged co-workers passionate about crafting impactful web solutions which transform the way our clients do business.\n\nAll names and logos for [Selleo](https://selleo.com/about) are trademark of Selleo Labs Sp. z o.o. (formerly Selleo Sp. z o.o. Sp.k.)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselleo%2Frspec-tapas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fselleo%2Frspec-tapas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselleo%2Frspec-tapas/lists"}