{"id":13879322,"url":"https://github.com/testdouble/cypress-rails","last_synced_at":"2025-07-16T15:32:09.515Z","repository":{"id":37458507,"uuid":"208565116","full_name":"testdouble/cypress-rails","owner":"testdouble","description":"Helps you write Cypress tests of your Rails app","archived":false,"fork":false,"pushed_at":"2024-09-25T23:29:19.000Z","size":639,"stargazers_count":321,"open_issues_count":29,"forks_count":48,"subscribers_count":9,"default_branch":"main","last_synced_at":"2024-11-17T14:23:11.346Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/testdouble.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2019-09-15T08:39:09.000Z","updated_at":"2024-11-13T02:30:59.000Z","dependencies_parsed_at":"2024-02-13T15:04:45.695Z","dependency_job_id":"a9383f6d-e659-4424-8eae-ccc71fdd7f7f","html_url":"https://github.com/testdouble/cypress-rails","commit_stats":{"total_commits":156,"total_committers":17,"mean_commits":9.176470588235293,"dds":0.25,"last_synced_commit":"9b3ed03514d00f0ae87ca484b08f8bbd158af102"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fcypress-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fcypress-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fcypress-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testdouble%2Fcypress-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/testdouble","download_url":"https://codeload.github.com/testdouble/cypress-rails/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226143895,"owners_count":17580245,"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":[],"created_at":"2024-08-06T08:02:17.196Z","updated_at":"2024-11-24T08:31:15.913Z","avatar_url":"https://github.com/testdouble.png","language":"Ruby","readme":"# cypress-rails\n\nThis is a simple gem to make it easier to start writing browser tests with\n[Cypress](http://cypress.io) for your [Rails](https://rubyonrails.org) apps,\nregardless of whether your app is server-side rendered HTML, completely\nclient-side JavaScript, or something in-between.\n\n## Installation\n\n**tl;dr**:\n\n1. Install the npm package `cypress`\n2. Install this gem `cypress-rails`\n3. Run `rake cypress:init`\n\n### Installing Cypress itself\n\nThe first step is making sure Cypress is installed (that's up to you, this\nlibrary doesn't install Cypress, it just provides a little Rails-specific glue).\n\nIf you're on newer versions of Rails and using\n[webpacker](https://www.github.com/rails/webpacker) for your front-end assets,\nthen you're likely already using yarn to manage your JavaScript dependencies. If\nthat's the case, you can add Cypress with:\n\n```sh\n$ yarn add --dev cypress\n```\n\nIf you're not using yarn in conjunction with your Rails app, check out the\nCypress docs on getting it installed. At the end of the day, this gem just needs\nthe `cypress` binary to exist either in `./node_modules/.bin/cypress` or on your\n`PATH`.\n\n### Installing the cypress-rails gem\n\nNow, to install the cypress-rails gem, you'll want to add it to your development\n\u0026 test gem groups of your Gemfile, so that you have easy access to its rake\ntasks:\n\n```ruby\ngroup :development, :test do\n  gem \"cypress-rails\"\nend\n```\n\nOnce installed, you'll want to run:\n\n```sh\n$ rake cypress:init\n```\n\nThis will override a few configurations in your `cypress.config.js` configuration\nfile.\n\n## Usage\n\n### Develop tests interactively with `cypress open`\n\nWhen writing tests with Cypress, you'll find the most pleasant experience (by\nway of a faster feedback loop and an interactive, easy-to-inspect test runner)\nusing the `cypress open` command.\n\nWhen using Rails, however, you'll also want your Rails test server to be running\nso that there's something for Cypress to interact with. `cypress-rails` provides\na wrapper for running `cypress open` with a dedicated Rails test server.\n\nSo, by running:\n\n```sh\n$ rake cypress:open\n```\n\nAny JavaScript files added to `cypress/integration` will be identified by\nCypress as tests. Simply click a test file in the Cypress application window to\nlaunch the test in a browser. Each time you save the test file, it will re-run\nitself.\n\n### Run tests headlessly with `cypress run`\n\nTo run your tests headlessly (e.g. when you're in CI), you'll want the `run`\ncommand:\n\n```sh\n$ rake cypress:run\n```\n\n## Managing your test data\n\nThe tricky thing about browser tests is that they usually depend on some test\ndata being available with which to exercise the app efficiently. Because cypress\nis a JavaScript-based tool and can't easily manipulate your Rails app directly,\ncypress-rails provides a number of hooks that you can use to manage your test\ndata.\n\nHere's what a `config/initializers/cypress_rails.rb` initializer might look\nlike:\n\n```ruby\nreturn unless Rails.env.test?\n\nCypressRails.hooks.before_server_start do\n  # Called once, before either the transaction or the server is started\nend\n\nCypressRails.hooks.after_transaction_start do\n  # Called after the transaction is started (at launch and after each reset)\nend\n\nCypressRails.hooks.after_state_reset do\n  # Triggered after `/cypress_rails_reset_state` is called\nend\n\nCypressRails.hooks.before_server_stop do\n  # Called once, at_exit\nend\n```\n\n(You can find [an\nexample\ninitializer](/example/config/initializers/cypress_rails_initializer.rb)\nin this repo.)\n\nThe gem also provides a special route on the test server:\n`/cypress_rails_reset_state`. Each time it's called, cypress-rails will do\ntwo things at the beginning of the next request received by the Rails app:\n\n* If `CYPRESS_RAILS_TRANSACTIONAL_SERVER` is enabled, roll back the transaction,\neffectively resetting the application state to whatever it was at the start of\nthe test run\n\n* Trigger any `after_state_reset` hooks you've configured (regardless of the\n  transactional server setting)\n\nThis way, you can easily instruct the server to reset its test state from your\nCypress tests like so:\n\n```js\nbeforeEach(() =\u003e {\n  cy.request('/cypress_rails_reset_state')\n})\n```\n\n(Remember, in Cypress, `before` is a before-all hook and `beforeEach` is run\nbetween each test case!)\n\n## Configuration\n\n### Environment variables\n\nThe cypress-rails gem is configured entirely via environment variables. If you\nfind yourself repeating a number of verbose environment variables as you run\nyour tests, consider invoking the gem from a custom script or setting your\npreferred environment variables project-wide using a tool like\n[dotenv](https://github.com/bkeepers/dotenv).\n\n\n* **CYPRESS_RAILS_DIR** (default: `Dir.pwd`) the directory of your Rails project\n* **CYPRESS_RAILS_CYPRESS_DIR** (default: _same value as `rails_dir`_) the directory of your Cypress project\n* **CYPRESS_RAILS_HOST** (default: `\"127.0.0.1\"`) the hostname to bind to\n* **CYPRESS_RAILS_PORT** (default: _a random available port_) the port to run\n  the Rails test server on\n* **CYPRESS_RAILS_BASE_PATH** (default: `\"/\"`) the base path for all Cypress's\n  requests to the app (e.g. via `cy.visit()`). If you've customized your\n  `baseUrl` setting (e.g. in `cypress.config.js`), you'll need to duplicate it with\n  this environment variable\n* **CYPRESS_RAILS_TRANSACTIONAL_SERVER** (default: `true`) when true, will start\n  a transaction on all database connections before launching the server. In\n  general this means anything done during `cypress open` or `cypress run` will\n  be rolled back on exit (similar to running a Rails System test)\n* **CYPRESS_RAILS_CYPRESS_OPTS** (default: _none_) any options you want to\n  forward to the Cypress CLI when running its `open` or `run` commands.\n\n#### Example: Running a single spec from the command line\n\nIt's a little verbose, but an example of using the above options to run a single\nCypress test would look like this:\n\n```\n$ CYPRESS_RAILS_CYPRESS_OPTS=\"--spec cypress/integration/a_test.js\" bin/rake cypress:run\n```\n\n#### Example: Running your tests in Chromium\n\nBy default, Cypress will run its tests in its packaged Electron app, unless you've configured it globally. To choose which browser it will run from the command line, try this:\n\n```\n$ CYPRESS_RAILS_CYPRESS_OPTS=\"--browser chromium\" bin/rake cypress:run\n```\n\n### Initializer hooks\n\n### before_server_start\n\nPass a block to `CypressRails.hooks.before_server_start` to register a hook that\nwill execute before the server or any transaction has been started. If you use\nRails fixtures, it may make sense to load them here, so they don't need to be\nre-inserted for each request\n\n### after_server_start\n\nPass a block to `CypressRails.hooks.after_server_start` to register a hook that\nwill execute after the server has booted.\n\n### after_transaction_start\n\nIf there's any custom behavior or state management you want to do inside the\ntransaction (so that it's also rolled back each time a reset is triggered),\npass a block to `CypressRails.hooks.after_transaction_start`.\n\n### after_state_reset\n\nEvery time the test server receives an HTTP request at\n`/cypress_rails_reset_state`, the transaction will be rolled back (if\n`CYPRESS_RAILS_TRANSACTIONAL_SERVER` is enabled) and the `after_state_reset`\nhook will be triggered. To set up the hook, pass a block to\n`CypressRails.hooks.after_state_reset`.\n\n### before_server_stop\n\nIn case you've made any permanent changes to your test database that could\npollute other test suites or scripts, you can use the `before_server_stop` to\n(assuming everything exits gracefully) clean things up and restore the state\nof your test database. To set up the hook, pass a block to\n`CypressRails.hooks.before_server_stop`.\n\n## Configuring Rails\n\nBeyond the configuration options above, you'll probably also want to disable caching\nin your Rails app's [config/environments/test.rb](/example/config/environments/test.rb#L9)\nfile, so that changes to your Ruby code are reflected in your tests while you\nwork on them with `rake cypress:open`. (If either option is set to\n`true`, any changes to your Ruby code will require a server restart to be reflected as you work\non your tests.)\n\nTo illustrate, here's what that might look like in `config/environments/test.rb`:\n\n```ruby\nconfig.cache_classes = false\nconfig.action_view.cache_template_loading = false\n```\n\n## Setting up continuous integration\n\n#### Circle CI\n\nNowadays, Cypress and Circle get along pretty well without much customization.\nThe only tricky bit is that Cypress will install its large-ish binary to\n`~/.cache/Cypress`, so if you cache your dependencies, you'll want to include\nthat path:\n\n```yml\nversion: 2\njobs:\n  build:\n    docker:\n      - image: circleci/ruby:2.6-node-browsers\n      - image: circleci/postgres:9.4.12-alpine\n        environment:\n          POSTGRES_USER: circleci\n    steps:\n      - checkout\n\n      # Bundle install dependencies\n      - type: cache-restore\n        key: v1-gems-{{ checksum \"Gemfile.lock\" }}\n\n      - run: bundle install --path vendor/bundle\n\n      - type: cache-save\n        key: v1-gems-{{ checksum \"Gemfile.lock\" }}\n        paths:\n          - vendor/bundle\n\n      # Yarn dependencies\n      - restore_cache:\n          keys:\n            - v1-yarn-{{ checksum \"yarn.lock\" }}\n            # fallback to using the latest cache if no exact match is found\n            - v1-yarn-\n\n      - run: yarn install\n\n      - save_cache:\n          paths:\n            - node_modules\n            - ~/.cache\n          key: v1-yarn-{{ checksum \"yarn.lock\" }}\n\n      # Run your cypress tests\n      - run: bin/rake cypress:run\n```\n\n## Why use this?\n\nRails ships with a perfectly competent browser-testing facility called [system\ntests](https://guides.rubyonrails.org/testing.html#system-testing) which depend\non [capybara](https://github.com/teamcapybara/capybara) to drive your tests,\nmost often with [Selenium](https://www.seleniumhq.org). All of these tools work,\nare used by lots of people, and are a perfectly reasonable choice when writing\nfull-stack tests of your Rails application.\n\nSo why would you go off the Rails to use Cypress and this gem, adding two\nadditional layers to the Jenga tower of testing facilities that Rails ships\nwith? Really, it comes down to the potential for an improved development\nexperience. In particular:\n\n* Cypress's [IDE-like `open`\n  command](https://docs.cypress.io/guides/getting-started/writing-your-first-test.html#Add-a-test-file)\n  provides a highly visual, interactive, inspectable test runner. Not only can\n  you watch each test run and read the commands as they're executed, Cypress\n  takes a DOM snapshot before and after each command, which makes rewinding and\n  inspecting the state of the DOM trivially easy, something that I regularly\n  find myself losing 20 minutes attempting to do with Capybara\n* `cypress open` enables an almost REPL-like feedback loop that is much faster\n  and more information dense than using Capybara and Selenium. Rather than\n  running a test from the command line, seeing it fail, then adding a debug\n  breakpoint to a test to try to manipulate the browser or tweaking a call to a\n  Capybara API method, failures tend to be rather obvious when using Cypress and\n  fixing it is usually as easy as tweaking a command, hitting save, and watching\n  it re-run\n* With very few exceptions, a Cypress test that works in a browser window will\n  also pass when run headlessly in CI\n* Cypress selectors are [just jQuery\n  selectors](https://api.jquery.com/category/selectors/), which makes them both\n  more familiar and more powerful than the CSS and XPath selectors offered by\n  Capybara. Additionally, Cypress makes it very easy to drop into a plain\n  synchronous JavaScript function for [making more complex\n  assertions](https://docs.cypress.io/guides/references/assertions.html#Should-callback)\n  or composing repetitive tasks into [custom\n  commands](https://docs.cypress.io/api/cypress-api/custom-commands.html#Syntax#article)\n* Cypress commands are, generally, much faster than analogous tasks in Selenium.\n  Where certain clicks and form inputs will hang for 300-500ms for seemingly no\n  reason when running against Selenium WebDriver, Cypress commands tend to run\n  as fast as jQuery can select and fill an element (which is, of course, pretty\n  fast)\n* By default, Cypress [takes a\n  video](https://docs.cypress.io/guides/guides/screenshots-and-videos.html#Screenshots#article)\n  of every headless test run, taking a lot of the mystery (and subsequent\n  analysis \u0026 debugging) out of test failures in CI\n\nNevertheless, there are trade-offs to attempting this (most notably around\nCypress's [limited browser\nsupport](https://docs.cypress.io/guides/guides/launching-browsers.html#Browsers)\nand the complications to test data management), and I wouldn't recommend\nadopting Cypress and writing a bunch of browser tests for every application.\nBut, if the above points sound like solutions to problems you experience, you\nmight consider trying it out.\n\n## Code of Conduct\n\nThis project follows Test Double's [code of\nconduct](https://testdouble.com/code-of-conduct) for all community interactions,\nincluding (but not limited to) one-on-one communications, public posts/comments,\ncode reviews, pull requests, and GitHub issues. If violations occur, Test Double\nwill take any action they deem appropriate for the infraction, up to and\nincluding blocking a user from the organization's repositories.\n\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestdouble%2Fcypress-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftestdouble%2Fcypress-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestdouble%2Fcypress-rails/lists"}