[
  {
    "path": ".codeclimate.yml",
    "content": "---\nversion: \"2\"\nchecks:\n  method-count:\n    enabled: false\n  file-lines:\n    config:\n      threshold: 500\n  method-complexity:\n    config:\n      threshold: 10\nengines:\n  bundler-audit:\n    enabled: false\n  csslint:\n    enabled: false\n  duplication:\n    enabled: true\n    exclude_patterns:\n    - \"lib/capybara/selector.rb\"\n    - \"lib/capybara/minitest.rb\"\n    - \"lib/capybara/selector/definition/\"\n    - \"lib/capybara/rspec/matchers/\"\n    config:\n      languages:\n        ruby:\n          mass_threshold: 25\n  eslint:\n    enabled: false\n  fixme:\n    enabled: true\n  rubocop:\n    enabled: true\n    channel: rubocop-0-72\n    exclude_fingerprints:\n    - affb30770e6ef0780044f5646e28d817\nratings:\n  paths:\n  - Gemfile.lock\n  - \"**.css\"\n  - \"**.inc\"\n  - \"**.js\"\n  - \"**.jsx\"\n  - \"**.module\"\n  - \"**.php\"\n  - \"**.py\"\n  - \"**.rb\"\nexclude_paths:\n- features/\n- spec/\n- lib/capybara/spec/\n"
  },
  {
    "path": ".gitattributes",
    "content": "lib/capybara/spec/views/*.erb eol=lf"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "**Note:** This is for issues with Capybara.  If you have a howto type question, please ask on the mailing list as requested in the README: http://groups.google.com/group/ruby-capybara\n\n## Meta\nCapybara Version:\n<!-- 2.8.1? -->\nDriver Information (and browser if relevant):\n<!-- selenium-webdriver 2.53.4 with Firefox 47.0.1? capybara-webkit? Poltergeist? -->\n\n## Expected Behavior\n\n## Actual Behavior\n<!-- include full stacktrace of any error -->\n\n## Steps to reproduce\n<!--\nPlease be sure to include the code that is creating the issue along with HTML the code is being run against\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/lock.yml",
    "content": "# Configuration for Lock Threads - https://github.com/dessant/lock-threads\n\n# Number of days of inactivity before a closed issue or pull request is locked\ndaysUntilLock: 30\n\n# Skip issues and pull requests created before a given timestamp. Timestamp must\n# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable\nskipCreatedBefore: false\n\n# Issues and pull requests with these labels will be ignored. Set to `[]` to disable\nexemptLabels: []\n\n# Label to add before locking, such as `outdated`. Set to `false` to disable\nlockLabel: false\n\n# Comment to post before locking. Set to `false` to disable\nlockComment: false\n\n# Assign `resolved` as the reason for locking. Set to `false` to disable\nsetLockReason: false\n\n# Limit to only `issues` or `pulls`\nonly: issues\n\n# Optionally, specify configuration settings just for `issues` or `pulls`\n# issues:\n#   exemptLabels:\n#     - help-wanted\n#   lockLabel: outdated\n\n# pulls:\n#   daysUntilLock: 30\n\n# Repository to extend settings from\n# _extends: repo"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "# This workflow will download a prebuilt Ruby version, install dependencies and\n# run tests with Rake\n# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby\n\nname: Build\n\n\"on\": push\n\nenv:\n  CUCUMBER_PUBLISH_QUIET: true\n  RUBYOPTS: \"--disable-did-you-mean\"\n  NOKOGIRI_USE_SYSTEM_LIBRARIES: true\n  JAVA_OPTS: \"-Djava.security.egd=file:/dev/urandom\"\n  WD_CACHE_TIME: 0\n\njobs:\n  rack_smoke:\n    runs-on: ubuntu-latest\n\n    env:\n      HTML5_PARSING: true\n\n    strategy:\n      fail-fast: false\n      matrix:\n        ruby: [\"3.2\", \"3.3\", \"3.4\"]\n        task: [\"rack_smoke\", \"cucumber\"]\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n      - name: Run smoke tests\n        run: bundle exec rake ${{ matrix.task }}\n\n  headless:\n    runs-on: ubuntu-latest\n\n    env:\n      HEADLESS: true\n\n    strategy:\n      # Ensure all jobs are run to completion\n      fail-fast: false\n      matrix:\n        ruby: [\"3.2\"]\n        task: [\"spec_chrome\", \"spec_firefox\"]\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n      - name: Run tests\n        run: bundle exec rake ${{ matrix.task }}\n\n  headless_base_versions:\n    runs-on: ubuntu-latest\n\n    env:\n      HEADLESS: true\n      BUNDLE_GEMFILE: gemfiles/Gemfile.base-versions\n\n    strategy:\n      # Ensure all jobs are run to completion\n      fail-fast: false\n      matrix:\n        ruby: [\"3.2\"]\n        task: [\"spec_chrome\", \"spec_firefox\"]\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install non-ruby dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install libxslt-dev\n\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n      - name: Run tests\n        run: bundle exec rake ${{ matrix.task }}\n\n  # remote_chrome:\n  #   runs-on: ubuntu-latest\n\n  #   strategy:\n  #     matrix:\n  #       ruby: [\"3.0\"]\n\n  #   steps:\n  #     - uses: actions/checkout@v4\n\n  #     - name: Set up Ruby\n  #       uses: ruby/setup-ruby@v1\n  #       with:\n  #         ruby-version: ${{ matrix.ruby }}\n  #         bundler-cache: true\n  #     - name: Run remote Chrome\n  #       run: docker-compose up -d selenium_chrome\n  #     - name: Run specs\n  #       run: bundle exec rake spec_chrome_remote\n\n  # remote_firefox:\n  #   runs-on: ubuntu-latest\n\n  #   strategy:\n  #     matrix:\n  #       ruby: [\"3.1\"]\n\n  #   steps:\n  #     - uses: actions/checkout@v4\n\n  #     - name: Set up Ruby\n  #       uses: ruby/setup-ruby@v1\n  #       with:\n  #         ruby-version: ${{ matrix.ruby }}\n  #         bundler-cache: true\n  #     - name: Run remote Firefox\n  #       run: docker-compose up -d selenium_firefox\n  #     - name: Run specs\n  #       run: bundle exec rake spec_firefox_remote\n\n  non_headless:\n    runs-on: ubuntu-latest\n\n    strategy:\n      # Ensure all jobs are run to completion\n      fail-fast: false\n      matrix:\n        ruby: [\"3.2\"]\n        task: [\"spec_chrome\", \"spec_firefox\"]\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install non-ruby dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install xvfb fluxbox\n\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n      - name: Run tests inside a window manager\n        run: xvfb-run sh -c \"fluxbox & bundle exec rake ${{ matrix.task }}; killall fluxbox\"\n\n  rack_3:\n    runs-on: ubuntu-latest\n\n    env:\n      HEADLESS: true\n      BUNDLE_GEMFILE: gemfiles/Gemfile.rack3\n\n    strategy:\n      fail-fast: false\n      matrix:\n        ruby: [\"3.4\"]\n        task: [\"spec_rack\"]\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n      - name: Run smoke tests\n        run: bundle exec rake ${{ matrix.task }}\n\n\n"
  },
  {
    "path": ".gitignore",
    "content": ".rbx\n.idea/\n.DS_Store\npkg\ntmp\n*~\n*swp\n*gem\nspec.opts\n.rvmrc\n.ruby-version\n.java-version\n.ruby-gemset\ncapybara-*.html\n.yardoc\ndoc\n.bundle\nGemfile*.lock\nchromedriver.log\nbundler_stubs\nbin\ngem-private_key.pem\nsave_path_tmp\nvendor/bundle\n.byebug_history\n"
  },
  {
    "path": ".rspec",
    "content": "--color\n--order random\n--require rspec/instafail\n--format RSpec::Instafail\n--format progress\n"
  },
  {
    "path": ".rubocop.yml",
    "content": "plugins:\n  - rubocop-minitest\n  - rubocop-performance\n  - rubocop-rake\n  - rubocop-capybara\n  - rubocop-rspec\n\nAllCops:\n  NewCops: enable\n  DisabledByDefault: false\n  TargetRubyVersion: 3.2\n  Exclude:\n      - 'vendor/**/*'\n      - 'gemfiles/vendor/**/*'\n\n#################### Capybara ##################\n\nCapybara/NegationMatcher:\n  Enabled: false\n\nRSpec/SpecFilePathFormat:\n  Enabled: false\n\nRSpec/SpecFilePathSuffix:\n  Enabled: false\n\nCapybara/FindAllFirst:\n  Enabled: false\n\nCapybara/NegationMatcherAfterVisit:\n  Enabled: false\n\nCapybara/RSpec/HaveSelector:\n  Enabled: false\n\nCapybara/SpecificFinders:\n  Enabled: false\n\nCapybara/ClickLinkOrButtonStyle:\n  Enabled: false\n\n#################### Gemspec ###################\n\nGemspec/DevelopmentDependencies:\n  Enabled: false\n\n#################### Layout ####################\n\nLayout/AccessModifierIndentation:\n  EnforcedStyle: outdent\n\nLayout/CaseIndentation:\n  EnforcedStyle: end\n\nLayout/EmptyLineBetweenDefs:\n  AllowAdjacentOneLineDefs: true\n\nLayout/EndAlignment:\n  EnforcedStyleAlignWith: variable\n\nLayout/FirstArrayElementIndentation:\n  EnforcedStyle: consistent\n\nLayout/IndentationWidth:\n  AllowedPatterns: ['^\\s*module']\n\nLayout/LineLength:\n  # Limit lines to 120 characters\n  # https://github.com/rubocop/ruby-style-guide#maximum-line-length\n  Exclude:\n    - 'spec/**/*'\n    - 'lib/capybara/spec/**/*'\n  AllowedPatterns:\n    - '\\s+# _?rubocop'\n    - '^\\s*#'\n    - '^\\s*(raise|warn|Capybara::Helpers.warn) '\n  Max: 120\n\n#################### Lint ####################\n\nLint/EmptyBlock:\n  Exclude:\n    - 'lib/capybara/spec/**/*'\n    - 'spec/**/*.rb'\n\nLint/UnusedMethodArgument:\n  Exclude:\n    - 'lib/capybara/driver/base.rb'\n    - 'lib/capybara/driver/node.rb'\n\n#################### Metrics ####################\n\nMetrics/AbcSize:\n  Enabled: false\n\nMetrics/BlockLength:\n  Exclude:\n    - 'spec/**/*'\n    - 'lib/capybara/spec/**/*'\n    - 'capybara.gemspec'\n  AllowedMethods:\n    - Capybara.add_selector\n    - Capybara::Selector::FilterSet.add\n\nMetrics/ClassLength:\n  CountComments: false\n  Enabled: false\n\nMetrics/CyclomaticComplexity:\n  Enabled: false\n\nMetrics/MethodLength:\n  CountComments: false\n  Enabled: false\n\nMetrics/ModuleLength:\n  Enabled: false\n  CountComments: false\n\nMetrics/ParameterLists:\n  CountKeywordArgs: false\n\nMetrics/PerceivedComplexity:\n  Enabled: false\n\n#################### Naming ####################\n\nNaming/MethodParameterName:\n  AllowedNames:\n    - 'el'\n    - 'id'\n    - 'c'\n    - 'x'\n    - 'y'\n    - 'on'\n\nNaming/PredicatePrefix:\n  Exclude:\n    - '**/*/*matchers.rb'\n    - '**/*/matchers/base.rb'\n    - '**/*/matchers/match_style.rb'\n\n#################### Performance ####################\n\nPerformance/MethodObjectAsBlock:\n  Enabled: false\n\nPerformance/StringIdentifierArgument:\n  Enabled: false\n\n#################### RSpec ####################\n\n# Capybara/FeatureMethods:\n#   Enabled: false\n\nRSpec/ContextWording:\n  Enabled: false\n\nRSpec/DescribeClass:\n  Enabled: false\n\nRSpec/ExampleLength:\n  Enabled: false\n\nRSpec/ExampleWording:\n  Enabled: false\n\n# RSpec/FilePath:\n#   Enabled: false\n\nRSpec/InstanceVariable:\n  AssignmentOnly: true\n\nRSpec/MultipleExpectations:\n  Enabled: false\n\nRSpec/NestedGroups:\n  Enabled: false\n\nRSpec/NoExpectationExample:\n  Enabled: false\n\nRSpec/PredicateMatcher:\n  Exclude:\n    - 'spec/basic_node_spec.rb'\n\n#################### Security ####################\n\nSecurity/YAMLLoad:\n  Exclude:\n    - 'lib/capybara/spec/**/*'\n    - 'spec/**/*'\n\n#################### Style ####################\n\nStyle/AccessorGrouping:\n  Enabled: false\n\nStyle/Alias:\n  Enabled: false\n\nStyle/ArgumentsForwarding:\n  Enabled: false\n\nStyle/ClassAndModuleChildren:\n  Enabled: false\n\nStyle/Documentation:\n  Exclude:\n    - 'lib/capybara/spec/**/*'\n    - 'spec/**/*'\n  Enabled: false\n\nStyle/DocumentDynamicEvalDefinition:\n  Enabled: false\n\nStyle/EmptyElse:\n  EnforcedStyle: empty\n\nStyle/IfUnlessModifier:\n  Exclude:\n    - 'spec/**/*'\n\nStyle/NumericLiterals:\n  Exclude:\n    - 'lib/capybara/spec/**/*'\n    - 'spec/**/*'\n\nStyle/ParallelAssignment:\n  Enabled: false\n\nStyle/SingleLineMethods:\n  Enabled: false\n\nStyle/SpecialGlobalVars:\n  Exclude:\n    - 'capybara.gemspec'\n\n### Enable and fix\nStyle/KeywordArgumentsMerging:\n  Enabled: false\n\nGemspec/AddRuntimeDependency:\n  Enabled: false\n\nLint/UselessConstantScoping:\n  Enabled: false\n\nNaming/PredicateMethod:\n  Enabled: false\n\nRSpec/IncludeExamples:\n  Enabled: false\n\nStyle/SuperArguments:\n  Enabled: false\n\nStyle/FileNull:\n  Enabled: false\n\nNaming/BlockForwarding:\n  Enabled: false\n\nStyle/ArrayIntersect:\n  Enabled: false"
  },
  {
    "path": ".yardopts",
    "content": "--markup markdown\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Questions about Capybara?\n\nTo get your questions answered, please ask on the [mailing list]. Do not open\nan issue.\n\n## Bug Reports\n\nIf you are at all unsure whether it's a bug in Capybara or a problem with your\ncode, post on the [mailing list] instead. If it turns out that it is a bug, we\ncan always open an issue later.\n\nIf you are sure that it's a bug in Capybara, open a new [issue] and try to\nanswer the following questions:\n\n- What did you do?\n- What did you expect to happen?\n- What happened instead?\n\nPlease also post code to replicate the bug. Ideally a failing test would be\nperfect, but even a simple script demonstrating the error would suffice. You\ncould use [this template](https://gist.github.com/jnicklas/5137053) as a\nstarting point. Please don't send us an entire application, unless the bug is\nin the *interaction* between Capybara and a particular framework.\n\nMake sure to specify which version of Capybara you are using.\n\nFeature requests are great, but they usually end up lying around the issue\ntracker indefinitely. Sending a pull request is a much better way of getting a\nparticular feature into Capybara.\n\n## Pull Requests\n\n- **Add tests!** Your patch won't be accepted if it doesn't have tests.  \nTo run a single test or scenario in development use `:focus_` metadata, e.g.:  \n`it 'should simulate multiple held down modifier keys', :focus_ do`\n\n- **Document any change in behaviour**. Make sure the README and any other\n  relevant documentation are kept up-to-date.\n\n- **Consider our release cycle**. We try to follow semver. Randomly breaking\n  public APIs is not an option.\n\n- **Create topic branches**. Don't ask us to pull from your master branch.\n\n- **One pull request per feature**. If you want to do more than one thing, send\n  multiple pull requests.\n\n- **Send coherent history**. Make sure each individual commit in your pull\n  request is meaningful. If you had to make multiple intermediate commits while\n  developing, please squash them before sending them to us.\n\n[mailing list]: http://groups.google.com/group/ruby-capybara\n[issue]: https://github.com/teamcapybara/capybara/issues\n"
  },
  {
    "path": "Gemfile",
    "content": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\ngem 'bundler', '< 3.0'\ngemspec\n\ngem 'xpath', github: 'teamcapybara/xpath'\n# gem 'rack-test', github: 'rack/rack-test'\n\ngroup :doc do\n  gem 'redcarpet', platforms: :mri\nend\n"
  },
  {
    "path": "History.md",
    "content": "# Version 3.40.0\nRelease date: 2024-01-26\n\n### Changned\n\n* Dropped support for Ruby 2.7, 3.0+ is now required\n* Dropped support for Selenium < 4.8\n* Use the new headless option on chromedriver with registered selenium driver [Neil Carvalho]\n\n### Added\n\n* `Capybara::Result#to_ary` to support multiple assignment [Sean Doyle]\n* `has_element?` and related matchers [Sean Doyle]\n*  Rack 3 support\n\n### Fixed\n\n* Forward save_screenshot options to selenium - Issue 2738\n* Rack test - don't auto submit forms with multiple inputs [Mitchell Henke]\n* Table row selector matches cell values in order - Issue 2686 [Jeff Parr]\n* Table row selector fixes for first column - Issue 2685 [Jeff Par]\n\n# Version 3.39.2\nRelease date: 2023-06-10\n\n### Fixed\n\n* Fix Selenium version comparison [aki77]\n\n# Version 3.39.1\nRelease date: 2023-05-12\n\n### Fixed\n\n* Fix usage of Selenium logger\n\n# Version 3.39.0\nRelease date: 2023-04-02\n\n### Added\n\n* Support `:target` filter option on `:link` selector [Yudai Takada]\n* Experimental Rack 3 support\n* Text normalization performance improvements [Brandon Weaver]\n\n### Fixed\n\n* MS Edge button click [Brian J. Bayer]\n* Options/Capabilities choosing based on Selenium versions\n* Support for base versions [Matijs van Zuijlen]\n* ExpectedError not defined in Selenium 4+\n* Filter block forwarding to a number of matchers [Christophe Bliard]\n###  Changed\n\n* Dropped support for rack 1.x\n\n# Version 3.38.0\nRelease date: 2022-11-03\n\n### Changed\n\n* Capybara.w3c_click_offset now defaults to true. If you need click offsets to be from the elements top left corner set it to false in your config\n\n### Added\n\n* Support Selenium 4.3 changes to click offset calculations\n* `click`, `double_click`, `right_click` can now be called on the session to click the currently scoped element (or document)\n* `Session#within` now passes the scoped element to the block\n* Support rack-test 2+\n* Retry interval is now configurable [Masahiro NOMOTO]\n* Support Puma 6 - Issue #2590\n* Selenium: DetachedShadowRootError is treated as an invalid element error [Perryn Fowler]\n* Selenium: When inspected shadow roots will have a tag name of \"ShadowRoot\"\n* `evaluate_async_script` added to Session::DSL_METHODS [Henry Blyth]\n\n### Fixed\n\n* Use higher precision clock in Capybara::Helpers::Timer if available\n* rack-test driver behavior with \\r\\n - Issue #2547 [Stefan Hoffmann]\n* Updated for deprecation of positional parameters in Selenium::WebDriver::ActionBuilder#pause\n* Explicitly set cause on server raised errors\n* Options no longer duplicated in have_xxx invalid option error message [Yudai Takada]\n* Animation disabler is now threadsafe [Daniel Sheppard]\n* Server connection count tracking [Oleksandr K.]\n* Ensure scopes are reset when session is [Henry Blyth]\n\n# Version 3.37.1\nRelease date: 2022-05-09\n\n### Fixed\n\n* Regression in rack-test visit - Issue #2548\n\n# Version 3.37.0\nRelease date: 2022-05-07\n\n### Changed\n\n* Ruby 2.7.0+ is now required\n\n### Added\n\n* [Beta] CSP nonces inserted into animation disabler additions - Issue #2542\n* Support `<base>` element in rack-test driver - ISsue #2544\n* [Beta] `Element#shadow_root` support. Requires selenium-webdriver 4.1+. Only currently supported with Chrome when using the selenium driver. Note: only CSS can be used to find elements from the shadow root. Therefore you won't be able to use most Capybara helper methods (`fill_in`, `click_link`, `find_field`, etc) directly from the shadow root since those locators are built using XPath. If you first locate a descendant from the shadow root using CSS then you should be able to use all the Capybara methods from there.\n* Regexp now supported for `exact_text` finder option\n\n### Fixed\n\n* Fragments in referer headers in rack-test driver - Issue #2525\n* Selenium v4.1 deprecation notice\n\n# Version 3.36.0\nRelease date: 2021-10-24\n\n### Changed\n\n* Ruby 2.6.0+ is now required\n* Minimum selenium-webdriver supported is now 3.142.7\n\n### Added\n\n* Support for selenium-webdriver 4.x\n* `allow_label_click` accepts click options to be used when clicking an associated label\n* Deprecated `allow_gumbo=` in favor of `use_html5_parsing=` to enable use of Nokogiri::HTML5 when available\n* `Session#active_element` returns the element with focus - Not supported by the `RackTest` driver [Sean Doyle]\n* Support `focused:` filter for finding interactive elements - Not supported by the `RackTest` driver [Sean Doyle]\n\n### Fixed\n\n* Sibling and ancestor queries now work with Simple::Node - Issue #2452\n* rack_test correctly ignores readonly attribute on specific input element types\n* `Node#all_text` always returns a string - Issue #2477\n* `have_any_of_selectors` negated match - Issue #2473\n* `Document#scroll_to` fixed for standards behavior - pass quirks: true if you need the older behavior [Eric Anderson]\n* Use capture on attach file event listener for better React compatibility [Jeff Way]\n* Animation disabler produces valid HTML [Javi Martin]\n\n### Removed\n\n* References to non-w3c mode in drivers/tests. Non-w3c mode is obsolete and no one should be using it anymore. Capybara hasn't been testing/supporting it in a while\n\n# Version 3.35.3\nRelease date: 2021-01-29\n\n### Fixed\n\n* Just a release to have the correct dates in the History.md in released gem\n\n# Version 3.35.2\nRelease date: 2021-01-29\n\n### Fixed\n\n* Selenium deprecation suppressor with Selenium 3.x\n\n# Version 3.35.1\nRelease date: 2021-01-26\n\n### Fixed\n\n* Default chrome driver registrations use chrome - Issue #2442 [Yuriy Alekseyev]\n* 'Capybara.test_id' usage with the :button selector - Issue #2443\n\n# Version 3.35.0\nRelease date: 2021-01-25\n\n### Added\n\n* Support Regexp matching for individual class names in :class filter passed an Array\n* Animation disabler now supports JQuery animation disabling when JQuery loaded from body [Chien-Wei Huang]\n\n### Fixed\n\n* :button selector type use with `enable_aria_role` [Sean Doyle]\n* <label> elements don't associate with aria-role buttons\n* Ignore Selenium::WebDriver::Error::InvalidSessionIdError when quitting driver [Robin Daugherty]\n* Firefox: Don't click input when sending keys if already focused\n* Miscellaneous issues with selenium-webdriver 4.0.0.alphas\n* Nil return error in node details optimizations\n* Animation disabler now inserts XHTML compliant content [Dale Morgan]\n\n# Version 3.34.0\nRelease date: 2020-11-26\n\n### Added\n\n* Ability to fill in with emoji when using Chrome with selenium driver (Firefox already worked)\n* Current path assertions/expectations accept optional filter block\n* Animation disabler now specifies `scroll-behavior: auto;` [Nathan Broadbent]\n* :button selector can now find elements by label text [Sean Doyle]\n* `Session#send_keys` to send keys to the current element with focus in drivers that support the\n  concept of a current element [Sean Doyle]\n\n### Changed\n\n* Text query validates the type parameter to prevent undefined behavior\n\n### Fixed\n\n* racktest driver better handles fragments and redirection to urls that include fragments\n* Don't error when attempting to get XPath location of a shadow element\n* Missing `readonly?` added to Node::Simple\n* Selenium version detection when loaded via alternate method [Joel Hawksley]\n* Connection count issue if REQUEST_URI value changed by app [Blake Williams]\n* Maintain URI fragment when redirecting in rack-test driver\n* Text query error message [Wojciech Wnętrzak]\n* Checking a checkbox/radio button with `allow_label_click` now works if there are multiple labels (Issue #2421)\n* `drop` with `Pathname` (Issue #2424)[Máximo Mussini]\n\n# Version 3.33.0\nRelease date: 2020-06-21\n\n### Added\n\n* Block passed to `within_session` now receives the new and old session\n* Support for aria-role button when enabled [Seiei Miyagi]\n* Support for aria-role link when enabled\n* Support for `validation_message` filter with :field and :fillable_field selectors\n* Deprecation warnings show source location [Koichi ITO]\n\n### Changed\n\n* Ruby 2.5.0+ is now required\n* Deprecated direct manipulation of the driver and server registries\n\n### Fixed\n\n* Ruby 2.7 warning in minitest `assert_text` [Eileen M. Uchitelle]\n\n\n# Version 3.32.2\nRelease date: 2020-05-16\n\n### Fixed\n\n* Don't use lazy enumerator with JRuby due to leaking threads\n* Ruby 2.7 deprecation warning when registering Webrick [Jon Zeppieri]\n* `have_text` description [Juan Pablo Rinaldi]\n\n# Version 3.32.1\nRelease date: 2020-04-05\n\n### Fixed\n\n* Rapid set now respects field maxlength (Issue #2332)\n* Only patch pause into legacy actions in Selenium < 4 (Issue #2334)\n\n# Version 3.32.0\nRelease date: 2020-03-29\n\n### Added\n\n* Support `delay` setting on click with Selenium\n* Implement rapid set for values longer than 30 characters in text fields with Selenium\n\n### Fixed\n\n* Result#[] and negative max on ranges (Issue #2302/2303) [Jeremy Evans]\n* RackTest form submission rewrites query string when using GET method\n* Ruby 2.7 deprecation warnings in RSpec matcher proxies\n\n# Version 3.31.0\nRelease date: 2020-01-26\n\n### Added\n\n* Support setting range inputs with the selenium driver [Andrew White]\n* Support setting range inputs with the rack driver\n* Support drop modifier keys in drag & drop [Elliot Crosby-McCullough]\n* `enabled_options` and `disabled options` filters for select selector\n* Support beginless ranges\n* Optionally allow `all` results to be reloaded when stable - Beta feature - may be removed in\n  future version if problems occur\n\n### Fixed\n\n* Fix Ruby 2.7 deprecation notices around keyword arguments. I have tried to do this without\n  any breaking changes, but due to the nature of the 2.7 changes and some selector types accepting\n  Hashes as locators there are a lot of edge cases. If you find any broken cases please report\n  them and I'll see if they're fixable.\n* Clicking on details/summary element behavior in rack_test driver_\n\n# Version 3.30.0\nRelease date: 2019-12-24\n\n### Added\n\n* Display pending requests when they don't complete in time [Juan Carlos Medina]\n* :order option in selector queries - set to :reverse to for reverse document order results\n* Support regexp for :name and :placeholder options in selectors that import filters from\n  _field filter set\n\n### Fixed\n\n* Issue around automatic port assignment - Issue #2245\n* Label selector when label has no id - Issue #2260\n* Preserve clientX/clientY in Selenium HTML5 drag emulation [Nicolò G.]\n* table selector using :with_cols option if last specified column matched but others didn't - Issue #2287\n* Some tests updated for Ruby 2.7 behavior change around keyword args\n\n# Version 3.29.0\nRelease date: 2019-09-02\n\n### Added\n\n* Allow clicking on file input when using the block version of `attach_file` with Chrome and Firefox\n* Spatial filters (`left_of`, `right_of`, `above`, `below`, `near`)\n* rack_test driver now supports clicking on details elements to open/close them\n\n### Fixed\n\n* rack_test driver correctly determines visibility for open details elements descendants\n\n### Changed\n\n* Results will now be lazily evaluated when using JRuby >= 9.2.8.0\n\n\n# Version 3.28.0\nRelease date: 2019-08-03\n\n### Added\n\n* Allow forcing HTML5 or legacy dragging via the `:html5` option to `drag_to` when using Selenium with Chrome or Firefox\n* Autodetection of drag type interprets not seeing the mousedown event as legacy.\n* HTML5 form validation `:valid` node filter added to `:field` and `:fillable_field` selectors\n* When using Capybara registered :puma server - patches Puma 4.0.x to fix SSL connection behavior. Removes\n  default `queue_requests` setting - Issue #2227\n\n# Version 3.27.0\nRelease date: 2019-07-28\n\n### Added\n\n* Allow to use chromedriver/geckodriver native `is_element_displayed` endpoint via Selenium\n  driver `native_displayed` option for performance reasons. Disabled by default due to endpoints\n  currently not handling &lt;details> element descendants visibility correctly.\n\n### Fixed\n\n* Ignore negative lookahead/lookbehind regex when performing initial XPath text matching\n* Reloading of elements found via `ancestor` and `sibling`\n* Only default puma settings to `queue_requests: false` when using SSL\n* Visibility of descendants of &lt;details> elements is correctly determined when using rack_test\n  and the selenium driver with Capybara optimized atoms\n* local/session storage clearance in Chrome when clearing only one of them - Issue #2233\n\n# Version 3.26.0\nRelease date: 2019-07-15\n\n### Added\n\n* `w3c_click_offset` configuration option applies to `right_click` and `double_click` as well as `click`\n* Warning when passing `nil` to the text/content assertions/expectations\n* `Session#server_url` returns the base url the AUT is being run at (when controlled by Capybara)\n* `option` selector type accepts an integer as locator\n\n### Fixed\n\n* Default puma server registration now specifies `queue_requests: false` - Issue #2227\n* Workaround issue with FF 68 and hanging during reset if a system modal is visible\n* Don't expand file path if it's already absolute - Issue #2228\n\n# Version 3.25.0\nRelease date: 2019-06-27\n\n### Added\n\n* Animation disabler also disables before and after pseudoelements - Issue #2221 [Daniel Heath]\n* `w3c_click_offset` configuration option to determine whether click offsets are calculated from element\n  center or top left corner\n\n### Fixed\n\n* Work around issue with chromedriver 76/77 in W3C mode losing mouse state during legacy drag. Only fixed if\n  both source and target are simultaneously inside the viewport - Issue #2223\n* Negative ancestor expectations/predicates were incorrectly checking siblings rather than ancestors\n\n# Version 3.24.0\nRelease date: 2019-06-13\n\n### Added\n\n* Log access when using the Selenium driver with Chrome 75 in W3C mode has been reenabled.\n\n### Changed\n\n* Selenium driver now selects all current content and then sends keys rather than clearing field by JS\n  and then sending keys when setting values to text inputs in order to more closely simulate user behavior\n\n### Fixed\n\n* Relative paths passed to `attach_file` will be assumed to be relative to the current working directory when using the\n  Selenium driver\n\n# Version 3.23.0\nRelease date: 2019-06-10\n\n### Added\n\n* Improved error message when using Chrome in W3C mode and attempting to access logs\n* Support driver specific options for Element#drag_to\n* Support setting `<input type=\"color\">` elements with the selenium driver\n\n### Fixed\n\n* Tightened conditions when in expression text option matching will be used\n* Improved Selenium drivers HTML5 drag and drop emulation compatibility with SortableJS library (and others)\n\n# Version 3.22.0\nRelease date: 2019-05-29\n\n### Added\n\n* `ancestor`/`sibling` assertions and matchers added\n* Documentation Updates and Fixes - Many thanks again to Masafumi Koba! [Masafumi Koba]\n* Added `:with` alias for `:option` filter on `:checkbox` and `:radio_button` selectors\n\n### Changed\n\n* Selenium driver with Chrome >= 73 now resets cookies and local/session storage after navigating\n  to 'about:blank' when possible to minimize potential race condition\n\n# Version 3.21.0\nRelease date: 2019-05-24\n\n### Added\n\n* Element#drop - Chrome and Firefox, via the selenium driver, support dropping files/data on elements\n* Default CSS used for `attach_file` `make_visible: true` now includes auto for\n  height and width to handle more ways of hiding the file input element\n* Documentation Updates and Fixes - Many thanks to Masafumi Koba! [Masafumi Koba]\n\n### Changed\n\n* Deprecate support for CSS locator being a Symbol\n\n# Version 3.20.2\nRelease date: 2019-05-19\n\n### Fixed\n\n* Move `uglifier` from runtime to development dependency [miyucy]\n\n# Version 3.20.1\nRelease date: 2019-05-17\n\n### Fixed\n\n* RackTest driver considers &lt;template> elements to be non-visible and ignores the contents\n\n# Version 3.20.0\nRelease date: 2019-05-14\n\n### Added\n\n* `Node#obscured?` to check viewport presence and element overlap\n* `:obscured` system filter to check whether elements are obscured in finders, assertions, and expectations\n* :label selector :for option can be a regexp\n* Significantly smaller `isDisplayed`/`getAttribute` atoms for selenium driver. If these produce issues you can disable their use\n  by setting an environment variable named 'DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS' (Please also report any issues).\n* `href: false` option with `find_link`/`click_link`/:link selector ignores `href` presence/absence\n\n### Fixed\n\n* Workaround Safari issue with send_keys not correctly using top level modifiers\n* Workaround Safari not retrying click due to incorrect error type\n* Fix Safari attach_file block mode when clicking elements associated to the file input\n* Workaround Safari issue with repeated hover\n\n# Version 3.19.1\nRelease date: 2019-05-11\n\n### Fixed\n\n* Fix access to specializations when Selenium::Driver is subclassed [James Mead]\n\n# Version 3.19.0\nRelease date: 2019-05-09\n\n### Added\n\n\n* Syntactic sugar `#once`, `#twice`, `#thrice`, `#exactly`, `#at_least`, `#at_most`, and `#times`\n  added to `have_selector`, `have_css`, `have_xpath`, and `have_text` RSpec matchers\n* Support for multiple expression types in Selector definitions\n* Reduced wirecalls for common actions in Selenium driver\n\n### Fixed\n\n* Workaround Chrome 75 appending files to multiple file inputs\n* Suppressed retry when detecting http vs https server connection\n\n# Version 3.18.0\nRelease date: 2019-04-22\n\n### Added\n\n* XPath Selector query optimized to make use of Regexp :text option in initial element find\n\n### Fixed\n\n* Workaround issue where Chrome/chromedriver 74 can return the wrong error type when a click is intercepted\n\n# Version 3.17.0\nRelease date: 2019-04-18\n\n### Added\n\n* Initial support for selenium-webdriver 4.0.0.alpha1\n* :button selector will now also match on `name` attribute\n\n### Fixed\n\n* Suppress warnings generated by using selenium-webdriver 3.141.5926\n* Mask Appium issue with finder visibility optimizations (non-optimal)\n\n# Version 3.16.2\nRelease date: 2019-04-10\n\n### Fixed\n\n* Fix Session#quit resetting of memoized document\n\n# Version 3.16.1\nRelease date: 2019-03-30\n\n### Fixed\n\n* Fix potential 'uninitialized constant' error when using the :selenium_chrome driver [jeffclemens-ab]\n\n# Version 3.16\nRelease date: 2019-03-28\n\n### Changed\n\n* Ruby 2.4.0+ is now required\n* Selenium driver now defaults to using a persistent http client connection\n\n### Added\n\n* :wait option in predicates now accepts `true` to selectively override when `Capybara.predicates_wait == false`\n\n# Version 3.15\nRelease date: 2019-03-19\n\n### Added\n\n* `attach_file` now supports a block mode on JS capable drivers to more accurately test user behavior when file inputs are hidden (beta)\n* :table selector now supports `with_rows`, 'rows', `with_cols`, and 'cols' filters\n\n### Fixed\n\n* Fix link selector when `Capybara.test_id` is set - Issue #2166 [bingjyang]\n\n\n# Version 3.14\nRelease date: 2019-02-25\n\n### Added\n\n* rack_test driver now supports reloading elements when the document changes - Issue #2157\n* Selenium driver HTML5 drag-drop emulation now emits multiple move events so drag direction\n  is determinable [Erkki Eilonen, Thomas Walpole]\n* Capybara.server_errors now defaults to [Exception] - Issue #2160 [Edgars Beigarts]\n### Fixed\n\n* Workaround hover issue with FF 65 - Issue #2156\n* Workaround chromedriver issue when setting blank strings to react controlled text fields\n* Workaround chromedriver issue with popup windows not loading content - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary\n\n# Version 3.13.2\nRelease date: 2019-01-24\n\n### Fixed\n\n* Remove extraneous output\n\n# Version 3.13.1\nRelease date: 2019-01-24\n\n### Fixed\n\n* Only use Selenium visibility optimization when JS atom is available - Issue #2151\n\n# Version 3.13.0\nRelease date: 2019-01-23\n\n### Added\n\n* Session#quit added\n* #scroll_to added to allow scrolling page/elements to specified locations\n* Speed optimizations around multiple element location and path generation when using the Selenium driver\n* Support for locator type checking in custom selectors\n* Allow configuration of gumbo use - defaults to off\n* `assert_style`/`has_style`/`have_style` deprecated in favor of `assert_matches_style`/`matches_styles?`/`match_style`\n* :style filter added to selectors\n\n# Version 3.12.0\nRelease date: 2018-11-28\n\n### Added\n\n* Support Ruby 2.6 endless range in Result#[] and query `:between` option\n* Pre-registered headless firefox driver :selenium_headless [Andrew Havens]\n* Selenium driver now defaults to clearing `sessionStorage` and `localStorage`. To disable pass `clear_local_storage: false` and/or `clear_session_storage: false` when creating Capybara::Selenium::Driver instance in your driver registration\n\n### Fixed\n\n* Raise error if only :x or :y are passed as an offset to click methods\n\n### Removed\n\n* Support for RSpec < 3.5\n\n# Version 3.11.1\nRelease date: 2018-11-16\n\n### Fixed\n\n* Fixed :link_or_button XPath generation when it has had an expression filter added\n\n# Version 3.11.0\nRelease date: 2018-11-14\n\n### Added\n\n* Ability for node filters to set detailed error messages\n* `Capybara::HTML` Will use `nokogumbo` for HTML parsing if installed\n* `Selector#locator_filter` added to allow for dynamic locator in selectors\n\n### Fixed\n\n* Node filters are evaluated in the context of the Selector they are used in to ensure the correct options are used\n\n# Version 3.10.1\nRelease date: 2018-11-03\n\n### Fixed\n\n* Fix `aria-label` and `test_id` matching for `link_or_button` selector type - Issue #2125\n* Fixed crash in element path creation for matcher failure messages - Issue #2120\n\n# Version 3.10.0\nRelease date: 2018-10-23\n\n### Added\n\n* :class filter can now check for class names starting with !\n* Selector `xpath`/`css` expression definitions will get filter names from block parameters if not explicitly provided\n* `any_of_selectors` assertions and matchers to complement `all_of_selectors` and `none_of_selectors`\n\n### Fixed\n\n* Selector `css` expression definition declared filters now work again\n* Cleaned up warnings [Yuji Yaginuma]\n* Workaround installation of rspec matcher proxies under jruby by reverting to the old solution not using prepend, so jruby bugs are not hit - Issue #2115\n\n# Version 3.9.0\nRelease date: 2018-10-03\n\n### Added\n\n* Selenium with Chrome removes all cookies at session reset instead of just cookies from current domain if possible\n* Support for Regexp for system :id and :class filters where possible\n* `using_session` now accepts a session object as well as the name of the session for users who  manually manage sessions\n* The `:field` selector will now find `type = \"hidden\"` fields if the `type: \"hidden\"` filter option is provided\n\n# Version 3.8.2\nRelease date: 2018-09-26\n\n### Fixed\n\n* Fixed negated class selector option - Issue #2103\n\n# Version 3.8.1\nRelease date: 2018-09-22\n\n### Fixed\n\n* Filling in of date fields with a string when using selenium chrome regression [Micah Geisel]\n\n# Version 3.8.0\nRelease date: 2018-09-20\n\n### Added\n\n* Workaround geckodriver 0.22 issue with undefined pause durations\n* :element selector ignores XML namespaces\n\n### Fixed\n\n* Added Errno::ECONNRESET to the errors which will allows https server detection\n\n# Version 3.7.2\nRelease date: 2018-09-12\n\n### Fixed\n\n* Fix MatchQuery based matchers when used on a root element found using any type of parent/ancestor query - Issue #2097\n\n* Fix Chrome/FF HTML5 drag simulation for elements (a, img) which default to draggable - Issue #2098\n\n# Version 3.7.1\nRelease date: 2018-09-05\n\n### Fixed\n\n* Restored ability to pass symbol as the CSS selector when calling `has_css?`/`have_css`/etc - Issue #2093\n\n# Version 3.7.0\nRelease date: 2018-09-02\n\n### Added\n\n* `Capybara.disable_animation` can be set to a CSS selector to identify which elements will have animation disabled [Michael Glass]\n* `Capybara.default_normalize_ws` option which sets whether or not text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) use `normalize_ws` option by default. Defaults to false. [Stegalin Ivan]\n* Selector based predicates, matchers, and finders now support the `:normalize_ws` option for the `:text`/`:exact_text` filters. Defaults to the `Capybara.default_normalize_ws`setting above.\n* Element `choose`/`check`/`uncheck`/`attach_file`/`fill_in` can now operate on the element they're called on or a descendant if no locator is passed.\n\n### Fixed\n\n* All CSS styles applied by the `Element#attach_file` `:make_visible` option will now have `!important` priority set to ensure they override any other specified style.\n* Firefox file inputs are only manually cleared when necessary.\n\n# Version 3.6.0\nRelease date: 2018-08-14\n\n### Added\n\n* Workaround geckodriver/firefox send_keys issues as much as possible using the Selenium actions API\n* Workaround lack of HTML5 native drag and drop events when using Selenium driver with Chrome and FF >= 62\n* `Capybara.predicates_wait` option which sets whether or not Capybaras matcher predicate methods (`has_css?`, `has_selector?`, `has_text?`, etc.) default to using waiting/retrying behavior (defaults to true)\n\n# Version 3.5.1\nRelease date: 2018-08-03\n\n### Fixed\n\n* Fixed misspelled method name `refute_matches_elector` => `refute_matches_selector`\n\n# Version 3.5.0\nRelease date: 2018-08-01\n\n### Added\n\n* text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) now support a `normalize_ws` option\n\n### Fixed\n\n* `attach_file` with Selenium and local Firefox 62+ now correctly generates only one change event when attaching multiple files\n\n# Version 3.4.2\nRelease date: 2018-07-24\n\n### Fixed\n\n* `match_xxx` selectors and `matches_xxx?` predicates work correctly with elements found using a sibling selector - Issue #2073\n\n# Version 3.4.1\nRelease date: 2018-07-20\n\n### Fixed\n\n* `Session#evaluate_script` now strips the script in `Session` rather than only in the Selenium driver\n\n# Version 3.4.0\nRelease date: 2018-07-19\n\n### Fixed\n\n* Make selenium driver :backspace clear strategy work even if caret location is in middle of field content [Champier Cyril]\n* Selenium issue with fieldset nested in disabled fieldset not being considered disabled\n* `Session#evaluate_script` and `Element#evaluate_script` now strip leading/trailing whitespace from scripts [Ian Lesperance]\n\n### Added\n\n* Work around Selenium lack of support for `file_detector` with remote geckodriver\n* `#within_frame` locator is optional when only one frame exists\n* `Capybara.test_id` option that allows for matching the Capybara provided selector types on an arbitrary attribute\n  (defaults to nil), set to your test id attribute ('data-test-id, etc) if using test id attributes in your project\n\n# Version 3.3.1\nRelease date: 2018-06-27\n\n### Fixed\n\n* `selenium-webdriver` version check [ahorek]\n* Selenium driver correctly responds to `disabled?` for fieldset elements - Issue #2059 [Thomas Walpole]\n\n# Version 3.3.0\nRelease date: 2018-06-25\n\n### Added\n\n* RackTest driver now handles 307/308 redirects\n* `execute_async_script` can now be called on elements to run the JS in the context of the element\n* `:download` filter option on `:link' selector\n* `Window#fullscreen`\n* `Element#style` and associated matchers\n\n### Changed\n\n* Minimum \"supported\" `selenium-webdriver` is raised to 3.5.0 (but you really should be using newer than that)\n\n### Fixes\n\n* Selenium driver with Firefox workaround for clicking on table row - https://github.com/mozilla/geckodriver/issues/1228\n* :class and :id filters applied to CSS based selectors now correctly handle the CSS comma\n* Selenium driver handles namespaces when generating an elements `#path` - Issue #2048\n\n# Version 3.2.1\nRelease date: 2018-06-04\n\n### Fixes\n\n* Only split CSS selectors when :class or :id options are given. Restores 3.1.1 functionality for now but the underlying issue\n  will require a larger fix, hopefully coming soon. - Issue #2044 [Thomas Walpole]\n\n# Version 3.2.0\nRelease date: 2018-06-01\n\n### Changed\n\n* Ruby 2.3.0+ is now required\n* `ElementNotFound` errors raised in selector filters are interpreted as non-matches\n\n### Added\n\n* New global configuration `default_set_options` used in `Capybara::Node::Element#set` as default `options` hash [Champier Cyril]\n* `execute_script` and `evaluate_script` can now be called on elements to run the JS in the context of the element [Thomas Walpole]\n* Filters in custom selectors now support a `matcher` Regexp to handle multiple filter options [Thomas Walpole]\n* `:element` selector type which will match on any attribute (other than the reserved names) passed as a filter option [Thomas Walpole]\n* `:class` filter option now supports preceding class names with `!` to indicate not having that class [Thomas Walpole]\n* `:class` and `:id` filter options now accept `XPath::Expression` objects to allow for more flexibility in matching [Thomas Walpole]\n* `Capybara.disable_animation` setting which triggers loading of a middleware that attempts to disable animations in pages.\n  This is very much a beta feature and may change/disappear in the future. [Thomas Walpole]\n\n# Version 3.1.1\nRelease date: 2018-05-25\n\n### Fixes\n\n* Ensure keystrokes are sent when setting time/date fields to a string with the Selenium driver [Thomas Walpole]\n\n# Version 3.1.0\nRelease date: 2018-05-10\n\n### Added\n\n* Support for using `select` with text inputs associated with a datalist element\n* `type` filter on `:button` selector\n* Support for server operating in https mode\n* Selenium driver now uses JS to fill_in/set date and time fields when passed date or time objects [Aleksei Gusev, Thomas Walpole]\n\n# Version 3.0.3\nRelease date: 2018-04-30\n\n### Fixes\n\n* Issue in `check` where the locator string could not be omitted\n* Selenium browser type detection when using remote [Ian Ker-Seymer]\n* Potential hang when waiting for requests to complete [Chris Zetter]\n\n# Version 3.0.2\nRelease date: 2018-04-13\n\n### Fixes\n\n* Fix expression filter descriptions in some selector failure messages\n* Fix compounding of negated matchers - Issue #2010\n\n# Version 3.0.1\nRelease date: 2018-04-06\n\n### Changed\n\n* Restored ability for `Capybara.server=` to accept a proc which was accidentally removed in 3.0.0\n\n# Version 3.0.0\nRelease date: 2018-04-05\n\n### Changed\n\n* Selenium driver only closes extra windows for browsers where that is known to work (Firefox, Chrome)\n* \"threadsafe\" mode is no longer considered beta\n\n### Fixes\n\n* Multiple file attach_file with Firefox\n* Use Puma::Server directly rather than Rack::Handler::Puma so signal handlers don't prevent test quitting\n\n# Version 3.0.0.rc2\nRelease date: 2018-03-23\n\n### Changed\n\n* Visible text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text\n* Drivers are expected to close extra windows when resetting the session\n* Selenium driver supports Date/Time when filling in date/time/datetime-local inputs\n* `current_url` returns the url for the top level browsing context\n* `title` returns the title for the top level browsing context\n\n### Added\n\n* `Driver#frame_url` returns the url for the current frame\n* `Driver#frame_title` returns the title for the current frame\n\n# Version 3.0.0.rc1\nRelease date: 2018-03-02\n\n### Added\n* Support for libraries wrapping Capybara elements and providing a `#to_capybara_node` method\n\n### Changed\n\n* `first` now raises ElementNotFound, by default, instead of returning nil when no matches are found  - Issue #1507\n* 'all' now waits for at least one matching element by default.  Pass `wait: false` if you want the previous\n  behavior where an empty result would be returned immediately if no matching elements exist yet.\n* ArgumentError raised if extra parameters passed to selector queries\n\n### Removed\n\n* Ruby < 2.2.2 support\n* `Capybara.exact_options` no longer exists. Just use `exact: true` on relevant actions/finders if necessary.\n* All previously deprecated methods removed\n* RSpec 2.x support\n* selenium-webdriver 2.x support\n* Nokogiri < 1.8 support\n* `field_labeled` alias for `find_field`\n\n# Version 2.18.0\nRelease date: 2018-02-12\n\n### Fixed\n\n* Firefox/geckodriver setting of contenteditable childs contents\n* Ignore Selenium::WebDriver::Error::SessionNotCreatedError when quitting driver [Tim Connor]\n\n### Removed\n\n* Headless chrome modal JS injection that is no longer needed for Chrome 64+/chromedriver 2.35+\n\n\n# Version 2.17.0\nRelease date: 2018-01-02\n\n### Added\n\n* `have_all_of_selectors`, `have_none_of_selectors` RSpec matchers for parity with minitest assertions [Thomas Walpole]\n\n### Fixed\n\n* Allow xpath 3.x gem [Thomas Walpole]\n* Issue when drivers returned nil for `current_path` and a matcher was used with a Regexp [Thomas Walpole]\n* Error message when visible element not found, but non-visible was [Andy Klimczak]\n\n# Version 2.16.1\nRelease date: 2017-11-20\n\n### Fixed\n\n* Fix rack_test driver for rack_test 0.7.1/0.8.0 [Thomas Walpole]\n* `accept_prompt` response text can contain quotes when using selenium with headless chrome [Thomas Walpole]\n\n# Version 2.16.0\nRelease date: 2017-11-13\n\n### Added\n\n* Attempt to move element into view when selenium doesn't correctly do it - See PR #1917 [Thomas Walpole]\n* `current_path` matchers will now autodetect path vs url based on string to be matched. Deprecates\n  `:only_path` in favor of `:ignore_query` option [Thomas Walpole]\n* Session#evaluate_async_script [Thomas Walpole]\n\n### Fixed\n\n* Default prompt value when using headless Chrome works correctly [Thomas Walpole]\n* Support new modal error returned by selenium-webdriver 3.7 for W3C drivers [Thomas Walpole]\n* Calling `respond_to?` on the object passed to `Capybara.configure` block - Issue #1935\n\n# Version 2.15.4\nRelease date: 2017-10-07\n\n### Fixed\n*  Visiting an absolute URL shouldn't overwrite the port when no server or always_include_port=false - Issue #1921\n\n# Version 2.15.3\nRelease date: 2017-10-03\n\n### Fixed\n*  Visiting '/' when Capybara.app_host has a trailing '/' - Issue #1918 [Thomas Walpole]\n\n# Version 2.15.2\nRelease date: 2017-10-02\n\n### Fixed\n\n*  Include within scope description in element not found/ambiguous errors [Thomas Walpole]\n*  Raise error when no activation block is passed to modal methods if using headless chrome [Thomas Walpole]\n*  Don't retry element access when inspecting [Ivan Neverov]\n*  Don't override a specified port (even if it is default port) in visited url [Thomas Walpole]\n\n# Version 2.15.1\n\nRelease date: 2017-08-04\n\n### Fixed\n\n*  `attach_file` with no extension/MIME type when using the `:rack_test` driver [Thomas Walpole]\n\n# Version 2.15.0\n\nRelease date: 2017-08-04\n\n### Added\n\n*  `sibling` and `ancestor` finders added [Thomas Walpole]\n*  Added ability to pass options to registered servers when setting\n*  Added basic built-in driver registrations `:selenium_chrome` and `:selenium_chrome_headless` [Thomas Walpole]\n*  Add `and_then` to Capybara RSpec matchers which behaves like the previous `and` compounder. [Thomas Walpole]\n*  Compound RSpec expectations with Capybara matchers now run both matchers inside a retry loop rather\n   than waiting for one to pass/fail before checking the second.  Will make `#or` more performant and confirm\n   both conditions are true \"simultaneously\" for `and`.  [Thomas Walpole]\n   If you still want the\n*  Default filter values are now included in error descriptions [Thomas Walpole]\n*  Add `Session#refresh` [Thomas Walpole]\n*  Loosened restrictions on where `Session#within_window` can be called from [Thomas Walpole]\n*  Switched from `mime-types` dependency to `mini_mime` [Jason Frey]\n\n# Version 2.14.4\n\nRelease date: 2017-06-27\n\n### Fixed\n\n* Fix retrieval of session_options for HaveSelector matcher descriptions - Issue #1883\n\n# Version 2.14.3\n\nRelease date: 2017-06-15\n\n### Fixed\n\n* Minitest assertions now raise the correct error type - Issue #1879 [Thomas Walpole]\n* Improve flexibility of detecting Chrome headless mode [Thomas Walpole]\n\n# Version 2.14.2\n\nRelease date: 2017-06-09\n\n### Fixed\n\n* Workaround for system modals when using headless Chrome now works if the page changes\n\n# Version 2.14.1\n\nRelease date: 2017-06-07\n\n### Fixed\n\n* Catch correct error when unexpected system modals are discovered in latest selenium [Thomas Walpole]\n* Update default `puma` server registration to encourage it to run in single mode [Thomas Walpole]\n* Suppress invalid element errors raised while lazily evaluating the results of `all` [Thomas Walpole]\n* Added missing `with_selected` option to the :select selector to match `options`/`with_options` options - Issue #1865 [Bartosz Nowak]\n* Workaround broken system modals when using selenium with headless Chrome\n\n# Version 2.14.0\n\nRelease date: 2017-05-01\n\n### Added\n\n* \"threadsafe\" mode that allows per-session configuration\n* `:type` filter added to the `:fillable_field` selector\n* Proxy methods when using RSpec for `all`/`within` that call either the Capybara::DSL or RSpec matchers\n  depending on arguments passed\n* Support for the new errors in selenium-webdriver 3.4\n\n### Fixed\n\n* Element#inspect doesn't raise an error on obsolete elements\n* Setting a contenteditable element with Selenium and Chrome 59\n* Workaround a hang while setting the window size when using geckodriver 0.16 and Firefox 53\n* Clicking on url with a blank href goes to the current url when using the RackTest driver\n\n# Version 2.13.0\n\nRelease date: 2017-03-16\n\n### Added\n\n* Selenium driver supports returning element(s) from evaluate_script [Thomas Walpole]\n* rack_test driver supports click on checkboxes and radio buttons to change their states [Thomas Walpole]\n* Support RSpec equivalent assertions and expectations for MiniTest [Thomas Walpole]\n\n### Fixed\n\n* Editing of content editable children with selenium\n\n# Version 2.12.1\n\nRelease date: 2017-02-16\n\n### Fixed\n*  Disable lazy Capybara::Results evaluation for JRuby due to ongoing issues\n\n# Version 2.12.0\n\nRelease date: 2017-01-22\n\n### Added\n\n* Session#switch_to_frame for manually handling frame switching - Issue #1365 [Thomas Walpole]\n* Session#within_frame now accepts a selector type (defaults to :frame) and locator [Thomas Walpole]\n* Session#execute_script and Session#evaluate_script now accept optional arguments that will be passed to the JS function.  This may not be supported\n  by all drivers, and the types of arguments that may be passed is limited.  If drivers opt to support this feature they should support passing page elements. [Thomas Walpole]\n* :exact option for text and title matchers - Issue #1256 [Thomas Walpole]\n* :exact_text option for selector finders/minders - Issue #1256 [Thomas Walpole]\n* Capybara.exact_text setting that affects the text matchers and :text options passed to selector finders/matchers. Issue #1256 [Thomas Walpole]\n* :make_visible option for #attach_file that allows for convenient changing of the CSS style of a file input element before attaching the file to it.  Requires driver\n  support for passing page elements to Session#execute_script [Thomas Walpole]\n* assert_all_selectors/assert_none_of_selectors assertions added\n* :link selector (used by find_link/click_link) now supports finding hyperlink placeholders (no href attribute) when href: nil option is specified [Thomas Walpole]\n* `within_element` as an alias of `within` due to RSpec collision\n\n### Fixed\n\n*  Fields inside a disabled fieldset are now correctly considered disabled - Issue #1816 [Thomas Walpole]\n*  Lazy Capybara::Results evaluation enabled for JRuby 9.1.6.0+\n*  A driver returning nil for #current_url won't raise an exception when calling #current_path [Dylan Reichstadt]\n*  Support Ruby 2.4.0 unified Integer [Koichi ITO]\n*  RackTest driver no longer modifies the text content of textarea elements in order to behave more like a real browser [Thomas Walpole]\n*  TextQuery (assert_text/have_text/etc) now ignores errors when trying to generate more helpful errors messages so the original error isn't hidden [Thomas Walpole]\n\n# Version 2.11.0\n\nRelease date: 2016-12-05\n\n### Added\n\n* Options for clearing session/local storage on reset added to the Selenium driver\n* Window size changes wait for the size to stabilize\n* Defined return value for most actions\n* Ignore specific error when quitting selenium driver instance - Issue #1773 [Dylan Reichstadt, Thomas Walpole]\n* Warn on selenium unknown errors rather than raising when quitting driver [Adam Pohorecki, Thomas Walpole]\n* Capybara::Result#each now returns an `Enumerator` when called without a block - Issue #1777 [Thomas Walpole]\n\n### Fixed\n\n* Selenium driver with Chrome should support multiple file upload [Thomas Walpole]\n* Fix visible: :hidden with :text option behavior [Thomas Walpole]\n\n# Version 2.10.2\n\nRelease date: 2016-11-30\n\n### Fixed\n\n* App exceptions with multiple parameter initializers now re-raised correctly - Issue #1785 [Michael Lutsiuk]\n* Use Addressable::URI when parsing current_path since it's more lenient of technically invalid URLs - Issue #1801 [Marcos Duque, Thomas Walpole]\n\n# Version 2.10.1\n\nRelease date: 2016-10-08\n\n### Fixed\n* App errors are now correctly raised with the explanatory cause in JRuby [Thomas Walpole]\n* Capybara::Result optimization disabled in JRuby due to issue with lazy enumerator evaluation [Thomas Walpole]\n  See: https://github.com/jruby/jruby/issues/4212\n\n# Version 2.10.0\n\nRelease date: 2016-10-05\n\n### Added\n\n* Select `<button>` elements with descendant images with `alt` attributes matching the locator [Ian Lesperance]\n* Locator string is optional in selector based matchers [Thomas Walpole]\n* Selectors can specify their default visible setting [Thomas Walpole]\n* Selector based finders and matchers can be passed a block to filter the results within the retry behavior [Thomas Walpole]\n\n# Version 2.9.2\n\nRelease date: 2016-09-29\n\n### Fixed\n\n* :label built-in selector finds nested label/control by control id if the label has no 'for' attribute [Thomas Walpole]\n* Warning issued if an unknown selector type is specified [Thomas Walpole]\n\n# Version 2.9.1\n\nRelease date: 2016-09-23\n\n### Fixed\n\n* allow_label_click option did not work in some cases with Poltergeist - Issue #1762 [Thomas Walpole]\n* matches_selector? should have access to all of a selectors options except the count options [Thomas Walpole]\n\n# Version 2.9.0\n\nRelease date: 2016-09-19\n\n### Fixed\n\n* Issue with rack-test driver and obsolete mime-types when using `#attach_file` - Issue #1756 [Thomas Walpole]\n\n### Added\n\n* `:class` option to many of the built-in selectors [Thomas Walpole]\n* Removed need to specify value when creating `:boolean` filter type in custom selectors [Thomas Walpole]\n* Filters can now be implemented through the XPath/CSS expressions in custom selectors [Thomas Walpole]\n* `Element#matches_xpath?` and `Element#matches_css?` [Thomas Walpole]\n\n# Version 2.8.1\n\nRelease date: 2016-08-25\n\n### Fixed\n\n* Fixed error message from have_text when text is not found but contains regex special characters [Ryunosuke Sato]\n* Warn when :exact option is passed that has no effect [Thomas Walpole]\n\n# Version 2.8.0\n\nRelease date: 2016-08-16\n\n### Fixed\n\n* Issue with modals present when closing the page using selenium - Issue #1696 [Jonas Nicklas, Thomas Walpole]\n* Server errors raised in test code have the cause set to an explanatory exception\n  in rubies that support Exception#cause rather than a confusing ExpectationNotMet - Issue #1719 [Thomas Walpole]\n* background/given/given! RSpec aliases will work if RSpec config.shared_context_metadata_behavior == :apply_to_host_groups [Thomas Walpole]\n* Fixed setting of unexpectedAlertError now that Selenium will be freezing the Capabilities::DEFAULTS [Thomas Walpole]\n\n### Added\n\n* 'check', 'uncheck', and 'choose' can now optionally click the associated label if the checkbox/radio button is not visible [Thomas Walpole]\n* Raise error if Capybara.app_host/default_host are specified incorrectly [Thomas Walpole]\n* Capybara::Selector::FilterSet allows for sharing filter definitions between selectors [Thomas Walpole]\n* Remove need to pass nil locator in most node actions when locator is not needed [Thomas Walpole]\n* New frames API for drivers - Issue #1365 [Thomas Walpole]\n* Deprecated Element#parent in favor of Element#query_scope to better indicate what it is [Thomas Walpole]\n* Improved error messages for have_text matcher [Alex Chaffee, Thomas Walpole]\n* The `:with` option for the field selector now accepts a regular expression for matching the field value [Uwe Kubosch]\n* Support matching on aria-label attribute when finding fields/links/buttons - Issue #1528 [Thomas Walpole]\n* Optimize Capybara::Result to only apply fields as necessary in common use-case of `.all[idx]` [Thomas Walpole]\n\n# Version 2.7.1\n\nRelease date: 2016-05-01\n\n### Fixed\n\n* Issue where within_Frame would fail with Selenium if the frame is removed from within itself [Thomas Walpole]\n* Reset sessions in reverse order so sessions with active servers are reset last - Issue #1692 [Jonas Nicklas, Thomas Walpole]\n\n# Version 2.7.0\n\nRelease date: 2016-04-07\n\n### Fixed\n\n* Element#visible?/checked?/disabled?/selected? Now return boolean as expected when using the rack_test driver [Thomas Walpole]\n* The rack_test driver now considers \\<input type=\"hidden\"> elements as non-visible [Thomas Walpole]\n* A nil locator passed to the built-in html type selectors now behaves consistently, and finds elements of the expected types [Thomas Walpole]\n* Capybara::Server now searches for available ports on the same interface it binds to [Aaron Stone]\n* Selenium Driver handles system modals that appear when page is unloading [Thomas Walpole]\n* Warning output if unused parameters are passed to a selector query [Thomas Walpole]\n\n### Added\n\n* Capybara now waits for requests to Capybaras server to complete while resetting the session [John Hawthorn, Thomas Walpole]\n* Capybara.reuse_server option to allow disabling of sharing server instance between sessions [Thomas Walpole]\n* :multiple filter added to relevant selectors [Thomas Walpole]\n* Provided server registrations for :webrick and :puma. Capybara.server = :puma for testing with Rails 5 [Thomas Walpole]\n* Deprecate passing a block to Capybara::server user Capybara::register_server instead [Thomas Walpole]\n* :option selector supports :selected and :disabled filters [Thomas Walpole]\n* Element#matches_selector? and associated matchers (match_selector, match_css, etc) for comparing an element to a selector [Thomas Walpole]\n* Deprecated Driver#browser_initialized? - Driver#reset! is required to be synchronous [Jonas Nicklas, Thomas Walpole]\n* Deprecated Capybara.save_and_open_page_path in favor of Capybara.save_path with slightly different behavior when using relative paths with\n  save_page/save_screenshot [Thomas Walpole]\n* :label selector [Thomas Walpole]\n\n# Version 2.6.2\n\nRelease date: 2016-01-27\n\n### Fixed\n\n* support for more than just addressable 2.4.0 [Thomas Walpole]\n\n# Version 2.6.1\n\nRelease date: 2016-01-27\n\n### Fixed\n\n* Add missing require for addressable [Jorge Bejar]\n\n# Version 2.6.0\n\nRelease date: 2016-01-17\n\n### Fixed\n\n* Fixed path escaping issue with current_path matchers [Thomas Walpole, Luke Rollans] (Issue #1611)\n* Fixed circular require [David Rodríguez]\n* Capybara::RackTest::Form no longer overrides Object#method [David Rodriguez]\n* options and with_options filter for :select selector have more intuitive visibility behavior [Nathan]\n* Test for nested modal API method support [Thomas Walpole]\n\n\n### Added\n\n* Capybara.modify_selector [Thomas Walpole]\n* xfeature and ffeature aliases added when using RSpec [Filip Bartuzi]\n* Selenium driver supports a :clear option to #set to handle different strategies for clearing a field [Thomas Walpole]\n* Support the use of rack 2.0 with the rack_test driver [Travis Grathwell, Thomas Walpole]\n* Disabled option for default selectors now supports true, false, or :all [Jillian Rosile, Thomas Walpole]\n* Modal API methods now default wait time to Capybara.default_max_wait_time [Thomas Walpole]\n\n# Version 2.5.0\n\nRelease date: 2015-08-25\n\n### Fixed\n\n* Error message now raised correctly when invalid options passed to 'have_text'/'have_content' [Thomas Walpole]\n* Rack-test driver correctly gets document title when elements on the page have nested title elements (SVG) [Thomas Walpole]\n* 'save_page' no longer errors when using Capybara.asset_host if the page has no \\<head> element [Travis Grathwell]\n* rack-test driver will ignore clicks on links with href starting with '#' or 'javascript:'\n\n### Added\n\n* has_current_path? and associated asserts/matchers added [Thomas Walpole]\n* Implement Node#path in selenium driver [Soutaro Matsumoto]\n* 'using_session' is now nestable [Thomas Walpole]\n* 'switch_to_window' will now use waiting behavior for a matching window to appear [Thomas Walpole]\n* Warning when attempting to select a disabled option\n* Capybara matchers are now available in RSpec view specs by default [Joshua Clayton]\n* 'have_link' and 'click_link' now accept Regexp for href matching [Yaniv Savir]\n* 'find_all' as an alias of 'all' due to collision with RSpec\n* Capybara.wait_on_first_by_default setting (default is false)\n  If set to true 'first' will use Capybaras waiting behavior to wait for at least one element to appear by default\n* Capybara waiting behavior uses the monotonic clock if supported to ease restrictions on freezing time in tests [Dmitry Maksyoma, Thomas Walpole]\n* Capybara.server_errors setting that allows to configure what type of errors will be raised from the server thread [Thomas Walpole]\n* Node#send_keys to allow for sending keypresses directly to elements [Thomas Walpole]\n* 'formmethod' attribute support in RackTest driver [Emilia Andrzejewska]\n* Clear field using backspaces in Selenium driver by using `:fill_options => { :clear => :backspace }` [Joe Lencioni]\n\n### Deprecated\n\n* Capybara.default_wait_time deprecated in favor of Capybara.default_max_wait_time to more clearly explain its purpose [Paul Pettengill]\n\n# Version 2.4.4\n\nRelease date: 2014-10-13\n\n### Fixed\n\n* Test for visit behavior updated [Phil Baker]\n* Removed concurrency prevention in favor of a note in the README - due to load order issues\n\n# Version 2.4.3\n\nRelease date: 2014-09-21\n\n### Fixed\n\n* Update concurrency prevention to match Rails 4.2 behavior\n\n# Version 2.4.2\n\nRelease date: 2014-09-20\n\n### Fixed\n\n* Prevent concurrency issue when testing Rails app with default test environment [Thomas Walpole]\n* Tags for windows API tests fixed [Dmitry Vorotilin]\n* Documentation Fixes [Andrey Botalov]\n* Always convert visit url to string, fixes issue with visit when always_include_port was enabled [Jake Goulding]\n* Check correct rspec version before including ::RSpec::Matchers::Composable in Capybara RSpec matchers [Thomas Walpole, Justin Ko]\n\n# Version 2.4.1\n\nRelease date: 2014-07-03\n\n### Added\n\n* 'assert_text', 'assert_no_text', 'assert_title', 'assert_no_title' methods added [Andrey Botalov]\n* have_title matcher now supports :wait option [Andrey Botalov]\n* More descriptive have_text error messages [Andrey Botalov]\n* New modal API ('accept_alert', 'accept_confirm', 'dismiss_confirm', 'accept_prompt', 'dismiss_prompt') - [Mike Pack, Thomas Walpole]\n* Warning when attempting to set contents of a readonly element\n* Suport for and/or compounding of Capybara's RSpec matchers for RSpec 3 [Thomas Walpole]\n* :fill_options option for 'fill_in' method that propagates to 'set' to allow for driver specific modification of how fields are filled in [Gabriel Sobrinho, Thomas Walpole]\n* Improved selector/filter description in failure messages [Thomas Walpole]\n\n### Fixed\n\n* HaveText error message now shows the text checked all the time\n* RackTest driver no longer attempts to follow an anchor tag without an href attribute\n* Warnings under RSpec 3\n* Handle URI schemes like about: correctly [Andrey Botalov]\n* RSpecs expose_dsl_globally option is now followed [Myron Marston, Thomas Walpole]\n\n# Version 2.3.0\n\nRelease date: 2014-06-02\n\n### Added\n\n* New window management API [Andrey Botalov]\n* Speed improvement for visible text detection in RackTest [Thomas Walpole]\n  Thanks to Phillipe Creux for instigating this\n* RSpec 3 compatability\n* 'save_and_open_screenshot' functionality [Greg Lazarev]\n* Server errors raised on visit and synchronize [Jonas Nicklas]\n\n### Fixed\n\n* CSSHandlers now derives from BasicObject so globally included functions (concat, etc) shouldn't cause issues [Thomas Walpole]\n* touched reset after session is reset [lesliepc16]\n\n# Version 2.2.1\n\nRelease date: 2014-01-06\n\n### Fixed\n\n* Reverted a change in 2.2.0 which navigates to an empty file on `reset`.\n  Capybara, now visits `about:blank` like it did before. [Jonas Nicklas]\n\n# Version 2.2.0\n\nRelease date: 2013-11-21\n\n### Added\n\n* Add `go_back` and `go_forward` methods. [Vasiliy Ermolovich]\n* Support RSpec 3 [Thomas Holmes]\n* `has_button?`, `has_checked_field?` and `has_unchecked_field?` accept\n  options, like other matchers. [Carol Nichols]\n* The `assert_selector` and `has_text?` methods now support the `:wait` option\n  [Vasiliy Ermolovich]\n* RackTest's visible? method now checks for the HTML5 `hidden` attribute.\n* Results from `#all` now delegate the `sample` method. [Phil Lee]\n* The `set` method now works for contenteditable attributes under Selenium.\n  [Jon Rowe]\n* radio buttons and check boxes can be filtered by option value, useful when\n  selecting by name [Jonas Nicklas]\n* feature blocks can be nested within other feature blocks in RSpec tests\n  [Travis Gaff]\n\n### Fixed\n\n* Fixed race conditions causing stale element errors when filtering by text.\n  [Jonas Nicklas]\n* Resetting the page is now synchronous and navigates to an empty HTML file,\n  instead of `about:blank`, fixing hanging issues in JRuby. [Jonas Nicklas]\n* Fixed cookies not being set when path is blank under RackTest [Thomas Walpole]\n* Clearing fields now correctly causes change events [Jonas Nicklas]\n* Navigating to an absolute URI without trailing slash now works as expected\n  under RackTest [Jonas Nicklas]\n* Checkboxes without assigned value default to `on` under RackTest [Nigel Sheridan-Smith]\n* Clicks on buttons with no form associated with them are ignored in RackTest\n  instead of raising an obscure exception. [Thomas Walpole]\n* execute_script is now a session method [Andrey Botalov]\n* Nesting `within_window` and `within_frame` inside `within` resets the scope\n  so that they behave like a user would expect [Thomas Walpole]\n* Improve handling of newlines in textareas [Thomas Walpole]\n* `Capybara::Result` delegates its inspect method, so as not to confuse users\n  [Sam Rawlins]\n* save_page always returns a full path, fixes problems with Launchy [Jonas Nicklas]\n* Selenium driver's `quit` method does nothing when browser hasn't been loaded\n  [randoum]\n* Capybara's WEBRick server now propertly respects the server_host option\n  [Dmitry Vorotilin]\n* gemspec now includes license information [Jonas Nicklas]\n\n# Version 2.1.0\n\nRelease date: 2013-04-09\n\n### Changed\n\n* Hard version requirement on Ruby >= 1.9.3. Capybara will no longer install\n  on 1.8.7. [Felix Schäfer]\n* Capybara no longer depends on the `selenium-webdriver` gem. Add it to\n  your Gemfile if you wish to use the Selenium driver. [Jonas Nicklas]\n* `Capybara.ignore_hidden_elements` defaults to `true`. [Jonas Nicklas]\n* In case of multiple matches `smart` matching is used by default. Set\n  `Capybara.match = :one` to revert to old behaviour. [Jonas Nicklas].\n* Options in select boxes use smart matching and no longer need to match\n  exactly. Set `Capybara.exact_options = false` to revert to old behaviour.\n  [Jonas Nicklas].\n* Visibility of text depends on `Capybara.ignore_hidden_elements` instead of\n  always returning only visible text. Set `Capybara.visible_text_only = true`\n  to revert to old behaviour. [Jonas Nicklas]\n* Cucumber cleans up session after scenario instead. This is consistent with\n  RSpec and makes more sense, since we raise server errors in `reset!`.\n  [Jonas Nicklas]\n\n### Added\n\n* All actions (`click_link`, `fill_in`, etc...) and finders now take an options\n  hash, which is passed through to `find`. [Jonas Nicklas]\n* CSS selectors are sent straight through to driver instead of being converted\n  to XPath first. Enables the use of some pseudo selectors, such as `invalid`\n  in some drivers. [Thomas Walpole]\n* `Capybara.asset_host` option, which inserts a `base` tag into the page on\n  `save_and_open_page`, eases debugging with the Rails asset pipeline.\n  [Steve Hull]\n* `exact` option, can specify whether to match substrings or entire text.\n  [Jonas Nicklas]\n* `match` option, can specify behaviour in case of multiple matches.\n  [Jonas Nicklas]\n* `wait` option, can specify how long to wait for a given action/finder.\n  [Jonas Nicklas]\n* Config option which disables bubbling of errors raised inside server.\n  [Jonas Nicklas]\n* `text` now takes a parameter which makes it possible to return either all\n  text or only visible text. The default depends on\n  `Capybara.ignore_hidden_elements`. `Capybara.visible_text_only` option is\n  available for compatibility. [Jonas Nicklas]\n* `has_content?` and `has_text?` now take the same count options as `has_selector?`\n  [Andrey Botalov]\n* `current_scope` is now public API, returns the current element when `within`\n  is used. [Martijn Walraven]\n* `find(\"input\").disabled?` returns true if a node is disabled. [Ben Lovell]\n* Find disabled fields and buttons with `:disabled => false`. [Jonas Nicklas]\n* `find(\"input\").hover` moves the mouse to the element in supported drivers.\n  [Thomas Walpole]\n* RackTest driver now support `form` attribute on form elements.\n  [Thomas Walpole]\n* `page.title` returns the page title. [Terry Progetto]\n* `has_title?` matcher to assert on page title. [Jonas Nicklas]\n* The gem is now signed with a certicficate. The public key is available in the\n  repo. [Jonas Nicklas]\n* `:select` and `:textarea` are valid options for the `:type` filter on `find_field`\n  and `has_field?`. [Yann Plancqueel]\n\n### Fixed\n\n* Fixed race conditions when synchronizing across multiple nodes [Jonas Nicklas]\n* Fixed race conditions in deeply nested selectors [Jonas Nicklas]\n* Fix issue with `within_frame`, where selecting multiple nested frames didn't\n  work as intended. [Thomas Walpole]\n* RackTest no longer fills in readonly textareas. [Thomas Walpole]\n* Don't use autoload to load files, require them directly instead. [Jonas Nicklas]\n* Rescue weird exceptions when booting server [John Wilger]\n* Non strings are now properly cast when using the maxlength attribute [Jonas Nicklas]\n\n# Version 2.0.3\n\nRelease date: 2013-03-26\n\n* Check against Rails version fixed to work with Rails' master branch now returning\n  a Gem::Version [Jonas Nicklas]\n* Use posix character class for whitespace replace, solves various encoding\n  problems on Ruby 2.0.0 and JRuby. [Ben Cates]\n\n# Version 2.0.2\n\nRelease date: 2012-12-31\n\n### Changed\n\n* Capybara no longer uses thin as a server if it is available, due to thread\n  safety issues. Now Capybara always defaults to WEBrick. [Jonas Nicklas]\n\n### Fixed\n\n* Suppress several warnings [Kouhei Sutou]\n* Fix default host becoming nil [Brian Cardarella]\n* Fix regression in 2.0.1 which caused node comparisons with non node objects\n  to throw an exception [Kouhei Sotou]\n* A few changes to the specs, only relevant to driver authors [Jonas Nicklas]\n* Encoding error under JRuby [Piotr Krawiec]\n* Ruby 2 encoding fix [Murahashi Sanemat Kenichi]\n* Catch correct exception on server timeout [Jonathan del Strother]\n\n# Version 2.0.1\n\nRelease date: 2012-12-21\n\n### Changed\n\n* Move the RackTest driver override with the `:respect_data_method` option\n  enabled from capybara/rspec to capybara/rails, so that it is enabled in\n  Rails projects that don't use RSpec. [Carlos Antonio da Silva]\n* `source` is now an alias for `html`. RackTest no longer returns modifications\n  to `html`. This basically codifies the behaviour which we've had for a while\n  anyway, and should have minimal impact for end users. For driver authors, it\n  means that they only have to implement `html`, and not `source`. [Jonas\n  Nicklas]\n\n### Fixed\n\n* Visiting relative URLs when `app_host` is set and no server is running works\n  as expected. [Jonas Nicklas]\n* `fill_in` works properly under Selenium again when the caret is not at the\n  end of the field before the method is called. [Douwe Maan, Jonas Nicklas, Jari\n  Bakken]\n* `attach_file` can once again be given a Pathname [Jake Goulding]\n\n# Version 2.0.0\n\nRelease date: 2012-11-05\n\n### Changed\n\n* Dropped official support for Ruby 1.8.x. [Jonas Nicklas]\n* `respect_data_method` default to `false` for the RackTest driver in non-rails\n  applications. That means that Capybara no longer picks up `data-method=\"post\"`\n  et. al. from links by default when you haven't required capybara/rails\n  [Jonas Nicklas]\n* `find` now raises an error if more than one element was found. Since `find` is\n  used by most actions, like `click_link` under the surface, this means that all\n  actions need to unambiguous in the future. [Jonas Nicklas]\n* All methods which find or manipulate fields or buttons now ignore them when\n  they are disabled. [Jonas Nicklas]\n* Can no longer find elements by id via `find(:foo)`, use `find(\"#foo\")` or\n  `find_by_id(\"foo\")` instead. [Jonas Nicklas]\n* `Element#text` on RackTest now only returns visible text and normalizes\n  (strips) whitespace, as with Selenium [Mark Dodwell, Jo Liss]\n* `has_content?` now checks the text value returned by `Element#text`, as opposed to\n  querying the DOM. Which means it does not match hidden text.\n  [Ryan Montgomery, Mark Dodwell, Jo Liss]\n* #394: `#body` now returns the unmodified source (like `#source`), not the current\n  state of the DOM (like `#html`), by popular request [Jonas Nicklas]\n* `Node#all` no longer returns an array, but rather an enumerable `Capybara::Result`\n  [Jonas Nicklas]\n* The arguments to `select` and `unselect` needs to be the exact text of an option\n  in a select box, substrings are no longer allowed [Jonas Nicklas]\n* The `options` option to `has_select?` must match the exact set of options. Use\n  `with_options` for the old behaviour. [Gonzalo Rodriguez]\n* The `selected` option to `has_select?` must match all selected options for multiple\n  selects. [Gonzalo Rodriguez]\n* Various internals for running driver specs, this should only affect driver authors\n  [Jonas Nicklas]\n* Rename `Driver#body` to `Driver#html` (relevant only for driver authors) [Jo\n  Liss]\n\n### Removed\n\n* No longer possible to specify `failure_message` for custom selectors. [Jonas Nicklas]\n* #589: `Capybara.server_boot_timeout` has been removed in favor of a higher\n  (60-second) hard-coded timeout [Jo Liss]\n* `Capybara.prefer_visible_elements` has been removed, as it is no longer needed\n  with the changed find semantics [Jonas Nicklas]\n* `Node#wait_until` and `Session#wait_until` have been removed. See `Node#synchronize`\n  for an alternative [Jonas Nicklas]\n* `Capybara.timeout` has been removed [Jonas Nicklas]\n* The `:resynchronize` option has been removed from the Selenium driver [Jonas Nicklas]\n* The `rows` option to `has_table?` has been removed without replacement.\n  [Jonas Nicklas]\n\n### Added\n\n* Much improved error message [Jonas Nicklas]\n* Errors from inside the session for apps running in a server are raised when\n  session is reset [James Tucker, Jonas Nicklas]\n* A ton of new selectors built in out of the box, like `field`, `link`, `button`,\n  etc... [Adam McCrea, Jonas Nicklas]\n* `has_text?` has been added as an alias for `has_content?` [Jonas Nicklas]\n* Add `Capybara.server_host` option (default: 127.0.0.1) [David Balatero]\n* Add `:type` option for `page.has_field?` [Gonzalo Rodríguez]\n* Custom matchers can now be specified in CSS in addition to XPath [Jonas Nicklas]\n* `Node#synchronize` method to rerun a block of code if certain errors are raised\n  [Jonas Nicklas]\n* `Capybara.always_include_port` config option always includes the server port in\n  URLs when using `visit`. Facilitates testing different domain names. [Douwe Maan]\n* Redirect limit for RackTest driver is configurable [Josh Lane]\n* Server port can be manually specified during initialization of server.\n  [Jonas Nicklas, John Wilger]\n* `has_content?` and `has_text?` can be given a regular expression [Vasiliy Ermolovich]\n* Multiple files can be uploaded with `attach_file` [Jarl Friis]\n\n### Fixed\n\n* Nodes found via `all` are no longer reloaded. This fixes weird quirks where\n  nodes would seemingly randomly replace themselves with other nodes [Jonas Nicklas]\n* Session is only reset if it has been modified, dramatically improves performance if\n  only part of the test suite runs Capybara. [Jonas Nicklas]\n* Test suite now passes on Ruby 1.8 [Jo Liss]\n* #565: `require 'capybara/dsl'` is no longer necessary [Jo Liss]\n* `Rack::Test` now respects ports when changing hosts [Jo Liss]\n* #603: `Rack::Test` now preserves the original referer URL when following a\n  redirect [Rob van Dijk]\n* Rack::Test now does not send a referer when calling `visit` multiple times\n  [Jo Liss]\n* Exceptions during server boot now propagate to main thread [James Tucker]\n* RSpec integration now cleans up before the test instead of after [Darwin]\n* If `respect_data_method` is true, the data-method attribute can be capitalized\n  [Marco Antonio]\n* Rack app boot timing out raises an error as opposed to just logging to STDOUT\n  [Adrian Irving-Beer]\n* `#source` returns an empty string instead of nil if no pages have been visited\n  [Jonas Nicklas]\n* Ignore first leading newline in textareas in RackTest [Vitalii Khustochka]\n* `within_frame` returns the value of the given block [Alistair Hutchison]\n* Running `Node.set` on text fields will not trigger more than one change event\n  [Andrew Kasper]\n* Throw an error when an option is given to a finder method, like `all` or\n  `has_selector?` which Capybara doesn't understand [Jonas Nicklas]\n* Two references to the node now register as equal when comparing them with `==`\n  [Jonas Nicklas]\n* `has_text` (`has_content`) now accepts non-string arguments, like numbers.\n  [Jo Liss]\n* `has_text` and `text` now correctly normalize Unicode whitespace, such as\n  `&nbsp;`. [Jo Liss]\n* RackTest allows protocol relative URLs [Jonas Nicklas]\n* Arguments are cast to string where necessary, so that e.g. `click_link(:foo)` works\n  as expected. [Jonas Nicklas]\n* `:count => 0` now works as expected [Jarl Friis]\n* Fixed race conditions on negative assertions when removing nodes [Jonas Nicklas]\n\n# Version 1.1.4\n\nRelease date: 2012-11-28\n\n### Fixed\n\n* Fix more race conditions on negative assertions. [Jonas Nicklas]\n\n# Version 1.1.3\n\nRelease date: 2012-10-30\n\n### Fixed:\n\n* RackTest driver ignores leading newline in textareas, this is consistent with\n  the spec and how browsers behave. [Vitalii Khustochka]\n* Nodes found via `all` and `first` are never reloaded. This fixes issues where\n  a node would sometimes magically turn into a completely different node.\n  [Jonas Nicklas]\n* Fix race conditions on negative assertions. This fixes issues where removing\n  an element and asserting on its non existence could cause\n  StaleElementReferenceError and similar to be thrown. [Jonas Nicklas]\n* Options are no longer lost when reloading elements. This fixes issues where\n  reloading an element would cause a non-matching element to be found, because\n  options to `find` were ignored. [Jonas Nicklas]\n\n# Version 1.1.2\n\nRelease date: 2011-11-15\n\n### Fixed\n\n* #541: Make attach_file work with selenium-webdriver >=2.12 [Jonas Nicklas]\n\n# Version 1.1.0\n\nRelease date: 2011-09-02\n\n### Fixed\n\n* Sensible inspect for Capybara::Session [Jo Liss]\n* Fix headers and host on redirect [Matt Colyer, Jonas Nicklas, Kim Burgestrand]\n* using_driver now restores the old driver instead of reverting to the default [Carol Nichols]\n* Errors when following links relative to the root path under rack-test [Jonas Nicklas, Kim Burgestrand]\n* Make sure exit codes are propagated properly [Edgar Beigarts]\n\n### Changed\n\n* resynchronization is off by default under Selenium\n\n### Added\n\n* Elements are automatically reloaded (including parents) during wait [Jonas Nicklas]\n* Rescue driver specific element errors, such as the dreaded ObsoleteElementError and retry [Jonas Nicklas]\n* Raise an error if something has frozen time [Jonas Nicklas]\n* Allow within to take a node instead of a selector [Peter Williams]\n* Using wait_time_time to change wait time for a block of code [Jonas Nicklas, Kim Burgestrand]\n* Option for rack-test driver to disable data-method hack [Jonas Nicklas, Kim Burgestrand]\n\n# Version 1.0.1\n\nRelease date: 2011-08-12\n\n### Fixed\n\n* Dependend on selenium-webdriver ~>2.0 and fix deprecations [Thomas Walpole, Jo Liss]\n* Depend on Launch 2.0 [Jeremy Hinegardner]\n* Rack-Test ignores fill in on fields with maxlength=\"\"\n\n# Version 1.0.0\n\nRelease date: 2011-06-14\n\n### Added\n\n* Added DSL for acceptance tests, inspired by Luismi Cavallé's Steak [Luismi Cavalle and Jonas Nicklas]\n* Selenium driver automatically waits for AJAX requests to finish [mgiambalvo, Nicklas Ramhöj and Jonas Nicklas]\n* Support for switching between multiple named sessions [Tristan Dunn]\n* failure_message can be specified for Selectors [Jonas Nicklas]\n* RSpec matchers [David Chelimsky and Jonas Nicklas]\n* Added save_page to save tempfile without opening in browser [Jeff Kreeftmeijer]\n* Cucumber now switches automatically to a registered driver if the tag matches the name [Jonas Nicklas]\n* Added Session#text [Jonas Nicklas and Scott Cytacki]\n* Added Session#html as an alias for Session#body [Jo Liss]\n* Added Session#current_host method [Jonas Nicklas]\n* Buttons can now be clicked by title [Javier Martin]\n* :headers option for RackTest driver to set custom HTTP headers [Jonas Nicklas]\n\n### Removed\n\n* Culerity and Celerity drivers have been removed and split into separate gems [Gabriel Sobrinho]\n\n### Deprecated\n\n* `include Capybara` has been deprecated in favour of `include Capybara::DSL` [Jonas Nicklas]\n\n### Changed\n\n* Rack test driver class has been renamed from Capybara::Driver::RackTest to Capybara::RackTest::Driver [Jonas Nicklas]\n* Selenium driver class has been renamed from Capybara::Driver::Selenium to Capybara::Selenium::Driver [Jonas Nicklas]\n* Capybara now prefers visible elements over hidden elements, disable by setting Capybara.prefer_visible_elements = false [Jonas Nicklas and Nicklas Ramhöj]\n* For RSpec, :type => :request is now supported (and preferred over :acceptance) [Jo Liss]\n* Selenium driver tried to wait for AJAX requests to finish before proceeding [Jonas Nicklas and Nicklas Ramhöj]\n* Session no longer uses method missing, uses explicit delegates instead [Jonas Nicklas]\n\n### Fixed\n\n* The Rack::Test driver now respects maxlength on text fields [Guilherme Carvalho]\n* Allow for more than one save_and_open_page call per second [Jo Liss]\n* Automatically convert options to :count, :minimum, :maximum, etc. to integers [Keith Marcum]\n* Rack::Test driver honours maxlength on input fields [Guilherme Carvalho]\n* Rack::Test now works as expected with domains and subdomains [Jonas Nicklas]\n* Session is reset more thoroughly between tests. [Jonas Nicklas]\n* Raise error when uploading non-existent file [Jonas Nicklas]\n* Rack response body should respond to #each [Piotr Sarnacki]\n* Deprecation warnings with selenium webdriver 0.2.0 [Aaron Gibraltar]\n* Selenium Chrome no longer YELLS tagname [Carl Jackson & David W. Frank]\n* Capybara no longer strips encoding before sending to Rack [Jonas Nicklas]\n* Improve handling of relative URLs [John Barton]\n* Readd and fix build_rack_mock_session [Jonas Nicklas, Jon Leighton]\n\n# Version 0.4.1\n\nRelease date: 2011-01-21\n\n### Added\n\n* New click_on alias for click_link_or_button, shorter yet unambiguous. [Jonas Nicklas]\n* Finders now accept :visible => false which will find all elements regardless of Capybara.ignore_hidden_elements [Jonas Nicklas]\n* Configure how the server is started via Capybara.server { |app, port| ... }. [John Firebough]\n* Added :between, :maximum and :minimum options to has_selector and friends [James B. Byrne]\n* New Capybara.string util function which allows matchers on arbitrary strings, mostly for helper and view specs [David Chelimsky and Jonas Nicklas]\n* Server boot timeout is now configurable, via Capybara.server_boot_timeout [Adam Cigánek]\n* Built in support for RSpec [Jonas Nicklas]\n* Capybara.using_driver to switch to a different driver temporarily [Jeff Kreeftmeijer]\n* Added Session#first which is somewhat speedier than Session#all, use it internally for speed boost [John Firebaugh]\n\n### Changed\n\n* Session#within now accepts the same arguments as other finders, like Session#all and Session#find [Jonas Nicklas]\n\n### Removed\n\n* All deprecations from 0.4.0 have been removed. [Jonas Nicklas]\n\n### Fixed\n\n* Don't mangle URLs in save_and_open_page when using self-closing tags [Adam Spiers]\n* Catch correct error when server boot times out [Jonas Nicklas]\n* Celerity driver now properly passes through options, making it configurable [Jonas Nicklas]\n* Better implementation of attributes in C[ue]lerity, should fix issues with attributes with strange names [Jonas Nicklas]\n* Session#find no longer swallows errors [Jonas Nicklas]\n* Fix problems with multiple file inputs [Philip Arndt]\n* Submit multipart forms as multipart under rack-test even if they contain no files [Ryan Kinderman]\n* Matchers like has_select? and has_checked_field? now work with dynamically changed values [John Firebaugh]\n* Preserve order of rack params [Joel Chippindale]\n* RackTest#reset! is more thorough [Joel Chippindale]\n\n# Version 0.4.0\n\nRelease date: 2010-10-22\n\n### Changed\n\n* The Selector API was changed slightly, use Capybara.add_selector, see README\n\n### Fixed\n\n* Celerity driver is registered properly\n* has_selector? and has_no_selector? added to DSL\n* Multiple selects return correct values under C[cu]lerity\n* Naked query strings are handled correctly by rack-test\n\n# Version 0.4.0.rc\n\nRelease date: 2010-10-12\n\n### Changed\n\n* within and find/locate now follow the XPath spec in that //foo finds all nodes in the document, instead of\n  only for the context node. See this post for details: http://groups.google.com/group/ruby-capybara/browse_thread/thread/b129067979df21b3\n* within now executes within the first found instance of the selector, not in all of them\n* find now waits for AJAX requests and raises an exception when the element is not found (same as locate used to do)\n* The default selector is now CSS, not XPath\n\n### Deprecated\n\n* Session#click has been renamed click_link_or_button and the old click has been deprecated\n* Node#node has been renamed native\n* Node#locate is deprecated in favor of Node#find, which now behaves identically\n* Session#drag is deprecated, please use Node#drag_to(other_node) instead\n\n### Added\n\n* Pretty much everything is properly documented now\n* It's now possible to call all session methods on nodes, like `find('#foo').fill_in(...)`\n* Custom selectors can be added with Capybara::Selector.add\n* The :id selector is added by default, use it lile `find(:id, 'foo')` or `find(:foo)`\n* Added Node#has_selector? so any kind of selector can be queried.\n* Added Capybara.configure for less wordy configuration\n* Added within_window to switch between different windows (currently Selenium only)\n* Capybara.server_port to provide a fixed port if wanted (defaults to automatic selection)\n\n### Fixed\n\n* CSS selectors with multiple selectors, such as \"h1, h2\" now work correctly\n* Port is automatically assigned instead of guessing\n* Strip encodings in rack-test, no more warnings!\n* RackTest no longer submits disabled fields\n* Servers no longer output annoying debug information when started\n* TCP port selection is left to Ruby to decide, no more port guessing\n* Select boxes now return option value instead of text if present\n* The default has been changed from localhost to 127.0.0.1, should fix some obscure selenium bugs\n* RackTest now supports complex field names, such as foo[bar][][baz]\n\n# Version 0.3.9\n\nRelease date: 2010-07-03\n\n### Added\n\n* status_code which returns the HTTP status code of the last response (no Selenium!)\n* Capybara.save_and_open_page to store tempfiles\n* RackTest and Culerity drivers now clean up after themselves properly\n\n### Fixed\n\n* When no rack app is set and the app is called, a more descriptive error is raised\n* select now works with optgroups\n* Don't submit image buttons unless they were clicked under rack-test\n* Support custom field types under Selenium\n* Support input fields without a type, treat them as though they were text fields\n* Redirect now throws an error after 5 redirects, as per RFC\n* Selenium now properly raises an error when Node#trigger is called\n* Node#value now returns the correct value for textareas under rack-test\n\n# Version 0.3.8\n\nRelease date: 2010-05-12\n\n### Added\n\n* Within_frame method to execute a block of code within a particular iframe (Selenium only!)\n\n### Fixed\n\n* Single quotes are properly escaped with `select` under rack-test and Selenium.\n* The :text option for searches now escapes regexp special characters when a string is given.\n* Selenium now correctly checks already checked checkboxes (same with uncheck)\n* Timing issue which caused Selenium to hang under certain circumstances.\n* Selenium now resolves attributes even if they are given as a Symbol\n\n# Version 0.3.7\n\nRelease date: 2010-04-09\n\nThis is a drop in compatible maintenance release. It's mostly\nimportant for driver authors.\n\n### Added\n\n* RackTest scans for data-method which rails3 uses to change the request method\n\n### Fixed\n\n* Don't hang when starting server on Windoze\n\n### Changed\n\n* The driver and session specs are now located inside lib! Driver authors can simply require them.\n\n# Version 0.3.6\n\nRelease date: 2010-03-22\n\nThis is a maintenance release with minor bug fixes, should be\ndrop in compatible.\n\n### Added\n\n* It's now possible to load in external drivers\n\n### Fixed\n\n* has_content? ignores whitespace\n* Trigger events when choosing radios and checking checkboxes under Selenium\n* Make Capybara.app totally optional when running without server\n* Changed fallback host so it matches the one set up by Rails' integration tests\n\n# Version 0.3.5\n\nRelease date: 2010-02-26\n\nThis is a mostly backwards compatible release, it does break\nthe API in some minor places, which should hopefully not affect\ntoo many users, please read the release notes carefully!\n\n### Breaking\n\n* Relative searching in a node (e.g. find('//p').all('//a')) will now follow XPath standard\n  this means that if you want to find descendant nodes only, you'll need to prefix a dot!\n* `visit` now accepts fully qualified URLs for drivers that support it.\n* Capybara will always try to run a rack server, unless you set Capybara.run_sever = false\n\n### Changed\n\n* thin is preferred over mongrel and webrick, since it is Ruby 1.9 compatible\n* click_button and click will find <input type=\"button\">, clicking them does nothing in RackTest\n\n### Added\n\n* Much improved error messages in a multitude of places\n* More semantic page querying with has_link?, has_button?, etc...\n* Option to ignore hidden elements when querying and interacting with the page\n* Support for multiple selects\n\n### Fixed\n\n* find_by_id is no longer broken\n* clicking links where the image's alt attribute contains the text is now possible\n* within_fieldset and within_table work when the default selector is CSS\n* boolean attributes work the same across drivers (return true/false)\n"
  },
  {
    "path": "License.txt",
    "content": "(The MIT License)\n\nCopyright (c) 2009-2018 Thomas Walpole, Jonas Nicklas\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Capybara\n\n[![Build Status](https://github.com/teamcapybara/capybara/actions/workflows/build.yml/badge.svg)](https://github.com/teamcapybara/capybara/actions/workflows/build.yml)\n[![Code Climate](https://codeclimate.com/github/teamcapybara/capybara.svg)](https://codeclimate.com/github/teamcapybara/capybara)\n[![Coverage Status](https://coveralls.io/repos/github/teamcapybara/capybara/badge.svg?branch=master)](https://coveralls.io/github/teamcapybara/capybara?branch=master)\n\nCapybara helps you test web applications by simulating how a real user would\ninteract with your app. It is agnostic about the driver running your tests and\ncomes with Rack::Test and Selenium support built in. WebKit is supported\nthrough an external gem.\n\n## Support Capybara\n\nIf you and/or your company find value in Capybara and would like to contribute financially to its ongoing maintenance and development, please visit\n<a href=\"https://www.patreon.com/capybara\">Patreon</a>\n\n\n**Need help?** Ask on the discussions (please do not open an issue): https://github.com/orgs/teamcapybara/discussions/categories/q-a\n\n## Table of contents\n\n- [Key benefits](#key-benefits)\n- [Setup](#setup)\n- [Using Capybara with Cucumber](#using-capybara-with-cucumber)\n- [Using Capybara with RSpec](#using-capybara-with-rspec)\n- [Using Capybara with Test::Unit](#using-capybara-with-testunit)\n- [Using Capybara with Minitest](#using-capybara-with-minitest)\n- [Using Capybara with Minitest::Spec](#using-capybara-with-minitestspec)\n- [Drivers](#drivers)\n    - [Selecting the Driver](#selecting-the-driver)\n    - [RackTest](#racktest)\n    - [Selenium](#selenium)\n- [The DSL](#the-dsl)\n    - [Navigating](#navigating)\n    - [Clicking links and buttons](#clicking-links-and-buttons)\n    - [Interacting with forms](#interacting-with-forms)\n    - [Querying](#querying)\n    - [Finding](#finding)\n    - [Scoping](#scoping)\n    - [Working with windows](#working-with-windows)\n    - [Scripting](#scripting)\n    - [Modals](#modals)\n    - [Debugging](#debugging)\n- [Selectors](#selectors)\n    - [Name](#selectors-name)\n    - [Locator](#selectors-locator)\n    - [Filters](#selectors-filters)\n- [Matching](#matching)\n    - [Exactness](#exactness)\n    - [Strategy](#strategy)\n- [Transactions and database setup](#transactions-and-database-setup)\n- [Asynchronous JavaScript (Ajax and friends)](#asynchronous-javascript-ajax-and-friends)\n- [Using the DSL elsewhere](#using-the-dsl-elsewhere)\n- [Calling remote servers](#calling-remote-servers)\n- [Using sessions](#using-sessions)\n    - [Named sessions](#named-sessions)\n    - [Using sessions manually](#using-sessions-manually)\n- [XPath, CSS and selectors](#xpath-css-and-selectors)\n- [Beware the XPath // trap](#beware-the-xpath--trap)\n- [Configuring and adding drivers](#configuring-and-adding-drivers)\n- [Gotchas:](#gotchas)\n- [\"Threadsafe\" mode](#threadsafe-mode)\n- [Development](#development)\n\n## <a name=\"key-benefits\"></a>Key benefits\n\n- **No setup** necessary for Rails and Rack application. Works out of the box.\n- **Intuitive API** which mimics the language an actual user would use.\n- **Switch the backend** your tests run against from fast headless mode\n  to an actual browser with no changes to your tests.\n- **Powerful synchronization** features mean you never have to manually wait\n  for asynchronous processes to complete.\n\n## <a name=\"setup\"></a>Setup\n\nCapybara requires Ruby 3.0.0 or later. To install, add this line to your\n`Gemfile` and run `bundle install`:\n\n```ruby\ngem 'capybara'\n```\n\nIf the application that you are testing is a Rails app, add this line to your test helper file:\n\n```ruby\nrequire 'capybara/rails'\n```\n\nIf the application that you are testing is a Rack app, but not Rails, set Capybara.app to your Rack app:\n\n```ruby\nCapybara.app = MyRackApp\n```\n\nIf you need to test JavaScript, or if your app interacts with (or is located at)\na remote URL, you'll need to [use a different driver](#drivers).  If using Rails 5.0+, but not using the Rails system tests from 5.1, you'll probably also\nwant to swap the \"server\" used to launch your app to Puma in order to match Rails defaults.\n\n```ruby\nCapybara.server = :puma # Until your setup is working\nCapybara.server = :puma, { Silent: true } # To clean up your test output\n```\n\n## <a name=\"using-capybara-with-cucumber\"></a>Using Capybara with Cucumber\n\nThe `cucumber-rails` gem comes with Capybara support built-in. If you\nare not using Rails, manually load the `capybara/cucumber` module:\n\n```ruby\nrequire 'capybara/cucumber'\nCapybara.app = MyRackApp\n```\n\nYou can use the Capybara DSL in your steps, like so:\n\n```ruby\nWhen /I sign in/ do\n  within(\"#session\") do\n    fill_in 'Email', with: 'user@example.com'\n    fill_in 'Password', with: 'password'\n  end\n  click_button 'Sign in'\nend\n```\n\nYou can switch to the `Capybara.javascript_driver` (`:selenium`\nby default) by tagging scenarios (or features) with `@javascript`:\n\n```ruby\n@javascript\nScenario: do something Ajaxy\n  When I click the Ajax link\n  ...\n```\n\nThere are also explicit tags for each registered driver set up for you (`@selenium`, `@rack_test`, etc).\n\n## <a name=\"using-capybara-with-rspec\"></a>Using Capybara with RSpec\n\nLoad RSpec 3.5+ support by adding the following line (typically to your\n`spec_helper.rb` file):\n\n```ruby\nrequire 'capybara/rspec'\n```\n\nIf you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works if\n[you have it configured in RSpec](https://rspec.info/features/6-0/rspec-rails/directory-structure/))\nand if you have your Capybara specs in a different directory, then tag the example groups with\n`type: :feature` or `type: :system` depending on which type of test you're writing.\n\nIf you are using Rails system specs please see [their documentation](https://rspec.info/features/6-0/rspec-rails/system-specs/system-specs)\nfor selecting the driver you wish to use.\n\nIf you are not using Rails, tag all the example groups in which you want to use\nCapybara with `type: :feature`.\n\nYou can now write your specs like so:\n\n```ruby\ndescribe \"the signin process\", type: :feature do\n  before :each do\n    User.create(email: 'user@example.com', password: 'password')\n  end\n\n  it \"signs me in\" do\n    visit '/sessions/new'\n    within(\"#session\") do\n      fill_in 'Email', with: 'user@example.com'\n      fill_in 'Password', with: 'password'\n    end\n    click_button 'Sign in'\n    expect(page).to have_content 'Success'\n  end\nend\n```\n\nUse `js: true` to switch to the `Capybara.javascript_driver`\n(`:selenium` by default), or provide a `:driver` option to switch\nto one specific driver. For example:\n\n```ruby\ndescribe 'some stuff which requires js', js: true do\n  it 'will use the default js driver'\n  it 'will switch to one specific driver', driver: :selenium\nend\n```\n\nCapybara also comes with a built in DSL for creating descriptive acceptance tests:\n\n```ruby\nfeature \"Signing in\" do\n  background do\n    User.create(email: 'user@example.com', password: 'caplin')\n  end\n\n  scenario \"Signing in with correct credentials\" do\n    visit '/sessions/new'\n    within(\"#session\") do\n      fill_in 'Email', with: 'user@example.com'\n      fill_in 'Password', with: 'caplin'\n    end\n    click_button 'Sign in'\n    expect(page).to have_content 'Success'\n  end\n\n  given(:other_user) { User.create(email: 'other@example.com', password: 'rous') }\n\n  scenario \"Signing in as another user\" do\n    visit '/sessions/new'\n    within(\"#session\") do\n      fill_in 'Email', with: other_user.email\n      fill_in 'Password', with: other_user.password\n    end\n    click_button 'Sign in'\n    expect(page).to have_content 'Invalid email or password'\n  end\nend\n```\n\n`feature` is in fact just an alias for `describe ..., type: :feature`,\n`background` is an alias for `before`, `scenario` for `it`, and\n`given`/`given!` aliases for `let`/`let!`, respectively.\n\nFinally, Capybara matchers are also supported in view specs:\n\n```ruby\nRSpec.describe \"todos/show.html.erb\", type: :view do\n  it \"displays the todo title\" do\n    assign :todo, Todo.new(title: \"Buy milk\")\n\n    render\n\n    expect(rendered).to have_css(\"header h1\", text: \"Buy milk\")\n  end\nend\n```\n\n**Note: When you require 'capybara/rspec' proxy methods are installed to work around name collisions between Capybara::DSL methods\n  `all`/`within` and the identically named built-in RSpec matchers. If you opt not to require 'capybara/rspec' you can install the proxy methods by requiring 'capybara/rspec/matcher_proxies' after requiring RSpec and 'capybara/dsl'**\n\n## <a name=\"using-capybara-with-testunit\"></a>Using Capybara with Test::Unit\n\n* If you are using `Test::Unit`, define a base class for your Capybara tests\n  like so:\n\n    ```ruby\n    require 'capybara/dsl'\n\n    class CapybaraTestCase < Test::Unit::TestCase\n      include Capybara::DSL\n\n      def teardown\n        Capybara.reset_sessions!\n        Capybara.use_default_driver\n      end\n    end\n    ```\n\n## <a name=\"using-capybara-with-minitest\"></a>Using Capybara with Minitest\n\n* If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.\n\n* If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`\n    file to make Capybara available in all test cases deriving from\n    `ActionDispatch::IntegrationTest`:\n\n    ```ruby\n    require 'capybara/rails'\n    require 'capybara/minitest'\n\n    class ActionDispatch::IntegrationTest\n      # Make the Capybara DSL available in all integration tests\n      include Capybara::DSL\n      # Make `assert_*` methods behave like Minitest assertions\n      include Capybara::Minitest::Assertions\n\n      # Reset sessions and driver between tests\n      teardown do\n        Capybara.reset_sessions!\n        Capybara.use_default_driver\n      end\n    end\n    ```\n\n* If you are not using Rails, define a base class for your Capybara tests like\n  so:\n\n    ```ruby\n    require 'capybara/minitest'\n\n    class CapybaraTestCase < Minitest::Test\n      include Capybara::DSL\n      include Capybara::Minitest::Assertions\n\n      def teardown\n        Capybara.reset_sessions!\n        Capybara.use_default_driver\n      end\n    end\n    ```\n\n    Remember to call `super` in any subclasses that override\n    `teardown`.\n\nTo switch the driver, set `Capybara.current_driver`. For instance,\n\n```ruby\nclass BlogTest < ActionDispatch::IntegrationTest\n  setup do\n    Capybara.current_driver = Capybara.javascript_driver # :selenium by default\n  end\n\n  test 'shows blog posts' do\n    # ... this test is run with Selenium ...\n  end\nend\n```\n\n## <a name=\"using-capybara-with-minitestspec\"></a>Using Capybara with Minitest::Spec\n\nFollow the above instructions for Minitest and additionally require capybara/minitest/spec\n\n```ruby\npage.must_have_content('Important!')\n```\n\n## <a name=\"drivers\"></a>Drivers\n\nCapybara uses the same DSL to drive a variety of browser and headless drivers.\n\n### <a name=\"selecting-the-driver\"></a>Selecting the Driver\n\nBy default, Capybara uses the `:rack_test` driver, which is fast but limited: it\ndoes not support JavaScript, nor is it able to access HTTP resources outside of\nyour Rack application, such as remote APIs and OAuth services. To get around\nthese limitations, you can set up a different default driver for your features.\nFor example, if you'd prefer to run everything in Selenium, you could do:\n\n```ruby\nCapybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered\n```\n\nHowever, if you are using RSpec or Cucumber (and your app runs correctly without JS),\nyou may instead want to consider leaving the faster `:rack_test` as the __default_driver__, and\nmarking only those tests that require a JavaScript-capable driver using `js: true` or\n`@javascript`, respectively.  By default, JavaScript tests are run using the\n`:selenium` driver. You can change this by setting\n`Capybara.javascript_driver`.\n\nYou can also change the driver temporarily (typically in the Before/setup and\nAfter/teardown blocks):\n\n```ruby\nCapybara.current_driver = :selenium # temporarily select different driver\n# tests here\nCapybara.use_default_driver       # switch back to default driver\n```\n\n**Note**: switching the driver creates a new session, so you may not be able to\nswitch in the middle of a test.\n\n### <a name=\"racktest\"></a>RackTest\n\nRackTest is Capybara's default driver. It is written in pure Ruby and does not\nhave any support for executing JavaScript. Since the RackTest driver interacts\ndirectly with Rack interfaces, it does not require a server to be started.\nHowever, this means that if your application is not a Rack application (Rails,\nSinatra and most other Ruby frameworks are Rack applications) then you cannot\nuse this driver. Furthermore, you cannot use the RackTest driver to test a\nremote application, or to access remote URLs (e.g., redirects to external\nsites, external APIs, or OAuth services) that your application might interact\nwith.\n\n[capybara-mechanize](https://github.com/jeroenvandijk/capybara-mechanize)\nprovides a similar driver that can access remote servers.\n\nRackTest can be configured with a set of headers like this:\n\n```ruby\nCapybara.register_driver :rack_test do |app|\n  Capybara::RackTest::Driver.new(app, headers: { 'HTTP_USER_AGENT' => 'Capybara' })\nend\n```\n\nSee the section on adding and configuring drivers.\n\n### <a name=\"selenium\"></a>Selenium\n\nCapybara supports [Selenium 3.5+\n(Webdriver)](https://www.seleniumhq.org/projects/webdriver/).\nIn order to use Selenium, you'll need to install the `selenium-webdriver` gem,\nand add it to your Gemfile if you're using bundler.\n\nCapybara pre-registers a number of named drivers that use Selenium - they are:\n\n  * :selenium                 => Selenium driving Firefox\n  * :selenium_headless        => Selenium driving Firefox in a headless configuration\n  * :selenium_chrome          => Selenium driving Chrome\n  * :selenium_chrome_headless => Selenium driving Chrome in a headless configuration\n\nThese should work (with relevant software installation) in a local desktop configuration but you may\nneed to customize them if using in a CI environment where additional options may need to be passed\nto the browsers.  See the section on adding and configuring drivers.\n\n\n**Note**: drivers which run the server in a different thread may not share the\nsame transaction as your tests, causing data not to be shared between your test\nand test server, see [Transactions and database setup](#transactions-and-database-setup) below.\n\n## <a name=\"the-dsl\"></a>The DSL\n\n*A complete reference is available at\n[rubydoc.info](http://rubydoc.info/github/teamcapybara/capybara/master)*.\n\n**Note: By default Capybara will only locate visible elements. This is because\n a real user would not be able to interact with non-visible elements.**\n\n**Note**: All searches in Capybara are *case sensitive*. This is because\nCapybara heavily uses XPath, which doesn't support case insensitivity.\n\n### <a name=\"navigating\"></a>Navigating\n\nYou can use the\n<tt>[visit](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#visit-instance_method)</tt>\nmethod to navigate to other pages:\n\n```ruby\nvisit('/projects')\nvisit(post_comments_path(post))\n```\n\nThe visit method only takes a single parameter, the request method is **always**\nGET.\n\nYou can get the [current path](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#current_path-instance_method)\nof the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:\n\n```ruby\nexpect(page).to have_current_path(post_comments_path(post))\n```\n\n**Note**: You can also assert the current path by testing the value of\n`current_path` directly. However, using the `have_current_path` matcher is\nsafer since it uses Capybara's [waiting behaviour](#asynchronous-javascript-ajax-and-friends)\nto ensure that preceding actions (such as a `click_link`) have completed.\n\n### <a name=\"clicking-links-and-buttons\"></a>Clicking links and buttons\n\n*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*\n\nYou can interact with the webapp by following links and buttons. Capybara\nautomatically follows any redirects, and submits forms associated with buttons.\n\n```ruby\nclick_link('id-of-link')\nclick_link('Link Text')\nclick_button('Save')\nclick_on('Link Text') # clicks on either links or buttons\nclick_on('Button Value')\n```\n\n### <a name=\"interacting-with-forms\"></a>Interacting with forms\n\n*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*\n\nThere are a number of tools for interacting with form elements:\n\n```ruby\nfill_in('First Name', with: 'John')\nfill_in('Password', with: 'Seekrit')\nfill_in('Description', with: 'Really Long Text...')\nchoose('A Radio Button')\ncheck('A Checkbox')\nuncheck('A Checkbox')\nattach_file('Image', '/path/to/image.jpg')\nselect('Option', from: 'Select Box')\n```\n\n### <a name=\"querying\"></a>Querying\n\n*Full reference: [Capybara::Node::Matchers](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers)*\n\nCapybara has a rich set of options for querying the page for the existence of\ncertain elements, and working with and manipulating those elements.\n\n```ruby\npage.has_selector?('table tr')\npage.has_selector?(:xpath, './/table/tr')\n\npage.has_xpath?('.//table/tr')\npage.has_css?('table tr.foo')\npage.has_content?('foo')\n```\n\n**Note:** The negative forms like `has_no_selector?` are different from `not\nhas_selector?`. Read the section on asynchronous JavaScript for an explanation.\n\nYou can use these with RSpec's magic matchers:\n\n```ruby\nexpect(page).to have_selector('table tr')\nexpect(page).to have_selector(:xpath, './/table/tr')\n\nexpect(page).to have_xpath('.//table/tr')\nexpect(page).to have_css('table tr.foo')\nexpect(page).to have_content('foo')\n```\n\n### <a name=\"finding\"></a>Finding\n\n_Full reference: [Capybara::Node::Finders](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders)_\n\nYou can also find specific elements, in order to manipulate them:\n\n```ruby\nfind_field('First Name').value\nfind_field(id: 'my_field').value\nfind_link('Hello', :visible => :all).visible?\nfind_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?\n\nfind_button('Send').click\nfind_button(value: '1234').click\n\nfind(:xpath, \".//table/tr\").click\nfind(\"#overlay\").find(\"h1\").click\nall('a').each { |a| a[:href] }\n```\n\nIf you need to find elements by additional attributes/properties you can also pass a filter block, which will be checked inside the normal waiting behavior.\nIf you find yourself needing to use this a lot you may be better off adding a [custom selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#add_selector-class_method) or [adding a filter to an existing selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#modify_selector-class_method).\n\n```ruby\nfind_field('First Name'){ |el| el['data-xyz'] == '123' }\nfind(\"#img_loading\"){ |img| img['complete'] == true }\n```\n\n**Note**: `find` will wait for an element to appear on the page, as explained in the\nAjax section. If the element does not appear it will raise an error.\n\nThese elements all have all the Capybara DSL methods available, so you can restrict them\nto specific parts of the page:\n\n```ruby\nfind('#navigation').click_link('Home')\nexpect(find('#navigation')).to have_button('Sign out')\n```\n\n### <a name=\"scoping\"></a>Scoping\n\nCapybara makes it possible to restrict certain actions, such as interacting with\nforms or clicking links and buttons, to within a specific area of the page. For\nthis purpose you can use the generic\n<tt>[within](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#within-instance_method)</tt>\nmethod. Optionally you can specify which kind of selector to use.\n\n```ruby\nwithin(\"li#employee\") do\n  fill_in 'Name', with: 'Jimmy'\nend\n\nwithin(:xpath, \".//li[@id='employee']\") do\n  fill_in 'Name', with: 'Jimmy'\nend\n```\n\nThere are special methods for restricting the scope to a specific fieldset,\nidentified by either an id or the text of the fieldset's legend tag, and to a\nspecific table, identified by either id or text of the table's caption tag.\n\n```ruby\nwithin_fieldset('Employee') do\n  fill_in 'Name', with: 'Jimmy'\nend\n\nwithin_table('Employee') do\n  fill_in 'Name', with: 'Jimmy'\nend\n```\n\n### <a name=\"working-with-windows\"></a>Working with windows\n\nCapybara provides some methods to ease finding and switching windows:\n\n```ruby\nfacebook_window = window_opened_by do\n  click_button 'Like'\nend\nwithin_window facebook_window do\n  find('#login_email').set('a@example.com')\n  find('#login_password').set('qwerty')\n  click_button 'Submit'\nend\n```\n\n### <a name=\"scripting\"></a>Scripting\n\nIn drivers which support it, you can easily execute JavaScript:\n\n```ruby\npage.execute_script(\"$('body').empty()\")\n```\n\nFor simple expressions, you can return the result of the script.\n\n```ruby\nresult = page.evaluate_script('4 + 4');\n```\n\nFor more complicated scripts you'll need to write them as one expression.\n\n```ruby\nresult = page.evaluate_script(<<~JS, 3, element)\n  (function(n, el){\n    var val = parseInt(el.value, 10);\n    return n+val;\n  })(arguments[0], arguments[1])\nJS\n```\n\n### <a name=\"modals\"></a>Modals\n\nIn drivers which support it, you can accept, dismiss and respond to alerts, confirms, and prompts.\n\nYou can accept alert messages by wrapping the code that produces an alert in a block:\n\n```ruby\naccept_alert 'optional text or regex' do\n  click_link('Show Alert')\nend\n```\n\nYou can accept or dismiss a confirmation by wrapping it in a block, as well:\n\n```ruby\naccept_confirm 'optional text' do\n  click_link('Show Confirm')\nend\n```\n\n```ruby\ndismiss_confirm 'optional text' do\n  click_link('Show Confirm')\nend\n```\n\nYou can accept or dismiss prompts as well, and also provide text to fill in for the response:\n\n```ruby\naccept_prompt('optional text', with: 'Linus Torvalds') do\n  click_link('Show Prompt About Linux')\nend\n```\n\n```ruby\ndismiss_prompt('optional text') do\n  click_link('Show Prompt About Linux')\nend\n```\n\nAll modal methods return the message that was presented. So, you can access the prompt message\nby assigning the return to a variable:\n\n```ruby\nmessage = accept_prompt(with: 'Linus Torvalds') do\n  click_link('Show Prompt About Linux')\nend\nexpect(message).to eq('Who is the chief architect of Linux?')\n```\n\n### <a name=\"debugging\"></a>Debugging\n\nIt can be useful to take a snapshot of the page as it currently is and take a\nlook at it:\n\n```ruby\nsave_and_open_page\n```\n\nYou can also retrieve the current state of the DOM as a string using\n<tt>[page.html](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#html-instance_method)</tt>.\n\n```ruby\nprint page.html\n```\n\nThis is mostly useful for debugging. You should avoid testing against the\ncontents of `page.html` and use the more expressive finder methods instead.\n\nFinally, in drivers that support it, you can save a screenshot:\n\n```ruby\npage.save_screenshot('screenshot.png')\n```\n\nOr have it save and automatically open:\n\n```ruby\nsave_and_open_screenshot\n```\n\nScreenshots are saved to `Capybara.save_path`, relative to the app directory.\nIf you have required `capybara/rails`, `Capybara.save_path` will default to\n`tmp/capybara`.\n\n## <a name=\"selectors\"></a>Selectors\n\nHelpers and matchers that accept Selectors share a common method signature that\nincludes:\n\n1. a positional Name argument\n2. a positional Locator argument\n3. keyword Filter arguments\n4. a predicate Filter block argument\n\nThese arguments are usually optional in one way or another.\n\n### <a name=\"selectors-name\"></a>Name\n\nThe name argument determines the Selector to use. The argument is optional when\na helper explicitly conveys the selector name (for example, [`find_field`][]\nuses `:field`, [`find_link`][] uses `:link`, etc):\n\n```ruby\npage.html # => '<a href=\"/\">Home</a>'\n\npage.find(:link) == page.find_link\n\npage.html # => '<input>'\n\npage.find(:field) == page.find_field\n```\n\n### <a name=\"selectors-locator\"></a>Locator\n\nThe locator argument usually represents information that can most meaningfully\ndistinguish an element that matches the selector from an element that does not:\n\n```ruby\npage.html # => '<div id=\"greeting\">Hello world</div>'\n\npage.find(:css, 'div').text     # => 'Hello world'\npage.find(:xpath, './/div').text # => 'Hello world'\n```\n\nGeneral purpose finder methods like [`find`][] and [`all`][] can accept the\nlocator as their first positional argument when the method can infer the default\nvalue from the [`Capybara.default_selector`][] configuration:\n\n```ruby\npage.html # => '<div id=\"greeting\">Hello world</div>'\n\nCapybara.default_selector = :css\n\npage.find('div').text     # => 'Hello world'\n\nCapybara.default_selector = :xpath\n\npage.find('.//div').text # => 'Hello world'\n```\n\nThe locator argument's semantics are context-specific, and depend on the\nselector. The types of arguments are varied. Some selectors support `String` or\n`Regexp` arguments, while others like `:table_row` support `Array<String>` and\n`Hash<String, String>`:\n\n```ruby\npage.html # => '<label for=\"greeting\">Greeting</label>\n          #     <input id=\"greeting\" name=\"content\">'\n\n# find by the <input> element's [id] attribute\npage.find(:id, 'greeting') == page.find_by_id('greeting') # => true\n\n# find by the <input> element's [id] attribute\npage.find(:field, 'greeting') == page.find_field('greeting') # => true\n\n# find by the <input> element's [name] attribute\npage.find(:field, 'content') == page.find_field('content') # => true\n\n# find by the <label> element's text\npage.find(:field, 'Greeting') == page.find_field('Greeting') # => true\n\npage.html # => '<table>\n          #       <tr>\n          #         <th>A</th>\n          #         <th>B</th>\n          #       </tr>\n          #       <tr>\n          #         <td>1</td>\n          #         <td>2</td>\n          #       </tr>\n          #     </table>'\n\n# find by <td> content\npage.find(:table_row, ['1', '2']) == page.find(:css, 'tr:last-of-type') # => true\n\n# find by <th> content paired with corresponding <td> content\npage.find(:table_row, 'A' => '1') == page.find(:table_row, 'B' => '2') # => true\n```\n\n### <a name=\"selectors-filters\"></a> Filters\n\nAll filters are optional. The supported set of keys is a mixture of both global\nand context-specific filters.The supported types of values depend on the\ncontext:\n\n```ruby\npage.html # => '<a href=\"/\">Home</a>'\n\n# find by the [href] attribute\npage.find_link(href: '/') == page.find_link(text: 'Home') # => true\n\npage.html # => '<div id=\"element\" data-attribute=\"value\">Content</div>'\n\n# find by the [id] attribute\npage.find(id: 'element') == page.find(text: 'Content') # => true\n\n# find by the [data-attribute] attribute\npage.find(:element, 'data-attribute': /value/) == page.find(text: 'Content') # => true\n\npage.html # => '<input type=\"checkbox\">'\n\n# find by the absence of the [checked] attribute\npage.find_field(checked: false) == page.find_field(unchecked: true) # => true\n```\n\nThe predicate block is always optional. When there are results for a selector\nquery, the block is called with each item in the result set. When the block\nevaluates to true, the item is included from the result set. Otherwise, the item\nis excluded:\n\n```ruby\npage.html # => '<input role=\"switch\" type=\"checkbox\" checked>'\n\nswitch = page.find_field { |input| input[\"role\"] == \"switch\" }\nfield = page.find_field(checked: true)\n\nswitch == field # => true\n```\n\n[`find`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find\n[`all`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:all\n[`Capybara.default_selector`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara%2Econfigure\n[`find_by_id`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_by_id\n[`find_field`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_field\n[`find_link`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_link\n\n## <a name=\"matching\"></a>Matching\n\nIt is possible to customize how Capybara finds elements. At your disposal\nare two options, `Capybara.exact` and `Capybara.match`.\n\n### <a name=\"exactness\"></a>Exactness\n\n`Capybara.exact` and the `exact` option work together with the `is` expression\ninside the XPath gem. When `exact` is true, all `is` expressions match exactly,\nwhen it is false, they allow substring matches. Many of the selectors built into\nCapybara use the `is` expression. This way you can specify whether you want to\nallow substring matches or not. `Capybara.exact` is false by default.\n\nFor example:\n\n```ruby\nclick_link(\"Password\") # also matches \"Password confirmation\"\nCapybara.exact = true\nclick_link(\"Password\") # does not match \"Password confirmation\"\nclick_link(\"Password\", exact: false) # can be overridden\n```\n\n### <a name=\"strategy\"></a>Strategy\n\nUsing `Capybara.match` and the equivalent `match` option, you can control how\nCapybara behaves when multiple elements all match a query. There are currently\nfour different strategies built into Capybara:\n\n1. **first:** Just picks the first element that matches.\n2. **one:** Raises an error if more than one element matches.\n3. **smart:** If `exact` is `true`, raises an error if more than one element\n   matches, just like `one`. If `exact` is `false`, it will first try to find\n   an exact match. An error is raised if more than one element is found. If no\n   element is found, a new search is performed which allows partial matches. If\n   that search returns multiple matches, an error is raised.\n4. **prefer_exact:** If multiple matches are found, some of which are exact,\n   and some of which are not, then the first exactly matching element is\n   returned.\n\nThe default for `Capybara.match` is `:smart`. To emulate the behaviour in\nCapybara 2.0.x, set `Capybara.match` to `:one`. To emulate the behaviour in\nCapybara 1.x, set `Capybara.match` to `:prefer_exact`.\n\n## <a name=\"transactions-and-database-setup\"></a>Transactions and database setup\n\n**Note:**  Rails 5.1+ \"safely\" shares the database connection between the app and test threads.  Therefore,\nif using Rails 5.1+ you SHOULD be able to ignore this section.\n\nSome Capybara drivers need to run against an actual HTTP server. Capybara takes\ncare of this and starts one for you in the same process as your test, but on\nanother thread. Selenium is one of those drivers, whereas RackTest is not.\n\nIf you are using a SQL database, it is common to run every test in a\ntransaction, which is rolled back at the end of the test, rspec-rails does this\nby default out of the box for example. Since transactions are usually not\nshared across threads, this will cause data you have put into the database in\nyour test code to be invisible to Capybara.\n\nCucumber handles this by using truncation instead of transactions, i.e. they\nempty out the entire database after each test. You can get the same behaviour\nby using a gem such as [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner).\n\n## <a name=\"asynchronous-javascript-ajax-and-friends\"></a>Asynchronous JavaScript (Ajax and friends)\n\nWhen working with asynchronous JavaScript, you might come across situations\nwhere you are attempting to interact with an element which is not yet present\non the page. Capybara automatically deals with this by waiting for elements\nto appear on the page.\n\nWhen issuing instructions to the DSL such as:\n\n```ruby\nclick_link('foo')\nclick_link('bar')\nexpect(page).to have_content('baz')\n```\n\nIf clicking on the *foo* link triggers an asynchronous process, such as\nan Ajax request, which, when complete will add the *bar* link to the page,\nclicking on the *bar* link would be expected to fail, since that link doesn't\nexist yet. However, Capybara is smart enough to retry finding the link for a\nbrief period of time before giving up and throwing an error. The same is true of\nthe next line, which looks for the content *baz* on the page; it will retry\nlooking for that content for a brief time. You can adjust how long this period\nis (the default is 2 seconds):\n\n```ruby\nCapybara.default_max_wait_time = 5\n```\n\nBe aware that because of this behaviour, the following two statements are **not**\nequivalent, and you should **always** use the latter!\n\n```ruby\n# Given use of a driver where the page is loaded when visit returns\n# and that Capybara.predicates_wait is `true`\n# consider a page where the `a` tag is removed through AJAX after 1s\nvisit(some_path)\n!page.has_xpath?('a')  # is false\npage.has_no_xpath?('a')  # is true\n```\n\nFirst expression:\n- `has_xpath?('a')` is called right after `visit` returns. It is `true` because the link has not yet been removed\n- Capybara does not wait upon successful predicates/assertions, therefore **has_xpath? returns `true` immediately**\n- The expression returns `false` (because it is negated with the leading `!`)\n\nSecond expression:\n- `has_no_xpath?('a')` is called right after `visit` returns. It is `false` because the link has not yet been removed.\n- Capybara waits upon failed predicates/assertions, therefore **has_no_xpath? does not return `false` immediately**\n- Capybara will periodically re-check the predicate/assertion up to the `default_max_wait_time` defined\n- after 1s, the predicate becomes `true` (because the link has been removed)\n- The expression returns `true`\n\nCapybara's RSpec matchers, however, are smart enough to handle either form.\nThe two following statements are functionally equivalent:\n\n```ruby\nexpect(page).not_to have_xpath('a')\nexpect(page).to have_no_xpath('a')\n```\n\nCapybara's waiting behaviour is quite advanced, and can deal with situations\nsuch as the following line of code:\n\n```ruby\nexpect(find('#sidebar').find('h1')).to have_content('Something')\n```\n\nEven if JavaScript causes `#sidebar` to disappear off the page, Capybara\nwill automatically reload it and any elements it contains. So if an AJAX\nrequest causes the contents of `#sidebar` to change, which would update\nthe text of the `h1` to \"Something\", and this happened, this test would\npass. If you do not want this behaviour, you can set\n`Capybara.automatic_reload` to `false`.\n\n## <a name=\"using-the-dsl-elsewhere\"></a>Using the DSL elsewhere\n\nYou can mix the DSL into any context by including <tt>Capybara::DSL</tt>:\n\n\n```ruby\nrequire 'capybara/dsl'\n\nCapybara.default_driver = :webkit\n\nmodule MyModule\n  include Capybara::DSL\n\n  def login!\n    within(:xpath, \".//form[@id='session']\") do\n      fill_in 'Email', with: 'user@example.com'\n      fill_in 'Password', with: 'password'\n    end\n    click_button 'Sign in'\n  end\nend\n```\n\nThis enables its use in unsupported testing frameworks, and for general-purpose scripting.\n\n## <a name=\"calling-remote-servers\"></a>Calling remote servers\n\nNormally Capybara expects to be testing an in-process Rack application, but you\ncan also use it to talk to a web server running anywhere on the internet, by\nsetting app_host:\n\n```ruby\nCapybara.current_driver = :selenium\nCapybara.app_host = 'http://www.google.com'\n...\nvisit('/')\n```\n\n**Note**: the default driver (`:rack_test`) does not support running\nagainst a remote server. With drivers that support it, you can also visit any\nURL directly:\n\n```ruby\nvisit('http://www.google.com')\n```\n\nBy default Capybara will try to boot a rack application automatically. You\nmight want to switch off Capybara's rack server if you are running against a\nremote application:\n\n```ruby\nCapybara.run_server = false\n```\n\n## <a name=\"using-sessions\"></a>Using sessions\n\nCapybara manages named sessions (:default if not specified) allowing multiple sessions using the same driver and test app instance to be interacted with.\nA new session will be created using the current driver if a session with the given name using the current driver and test app instance is not found.\n\n### Named sessions\nTo perform operations in a different session and then revert to the previous session\n\n```ruby\nCapybara.using_session(\"Bob's session\") do\n   #do something in Bob's browser session\nend\n #reverts to previous session\n```\n\nTo permanently switch the current session to a different session\n\n```ruby\nCapybara.session_name = \"some other session\"\n```\n\n### <a name=\"using-sessions-manually\"></a>Using sessions manually\n\nFor ultimate control, you can instantiate and use a\n[Session](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session)\nmanually.\n\n```ruby\nrequire 'capybara'\n\nsession = Capybara::Session.new(:webkit, my_rack_app)\nsession.within(\"form#session\") do\n  session.fill_in 'Email', with: 'user@example.com'\n  session.fill_in 'Password', with: 'password'\nend\nsession.click_button 'Sign in'\n```\n\n## <a name=\"xpath-css-and-selectors\"></a>XPath, CSS and selectors\n\nCapybara does not try to guess what kind of selector you are going to give it,\nand will always use CSS by default.  If you want to use XPath, you'll need to\ndo:\n\n```ruby\nwithin(:xpath, './/ul/li') { ... }\nfind(:xpath, './/ul/li').text\nfind(:xpath, './/li[contains(.//a[@href = \"#\"]/text(), \"foo\")]').value\n```\n\nAlternatively you can set the default selector to XPath:\n\n```ruby\nCapybara.default_selector = :xpath\nfind('.//ul/li').text\n```\n\nCapybara provides a number of other built-in selector types. The full list, along\nwith applicable filters, can be seen at [built-in selectors](https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Selector)\n\nCapybara also allows you to add custom selectors, which can be very useful if you\nfind yourself using the same kinds of selectors very often. The examples below are very\nsimple, and there are many available features not demonstrated. For more in-depth examples\nplease see Capybaras built-in selector definitions.\n\n```ruby\nCapybara.add_selector(:my_attribute) do\n  xpath { |id| XPath.descendant[XPath.attr(:my_attribute) == id.to_s] }\nend\n\nCapybara.add_selector(:row) do\n  xpath { |num| \".//tbody/tr[#{num}]\" }\nend\n\nCapybara.add_selector(:flash_type) do\n  css { |type| \"#flash.#{type}\" }\nend\n```\n\nThe block given to xpath must always return an XPath expression as a String, or\nan XPath expression generated through the XPath gem. You can now use these\nselectors like this:\n\n```ruby\nfind(:my_attribute, 'post_123') # find element with matching attribute\nfind(:row, 3) # find 3rd row in table body\nfind(:flash_type, :notice) # find element with id of 'flash' and class of 'notice'\n```\n\n## <a name=\"beware-the-xpath--trap\"></a>Beware the XPath // trap\n\nIn XPath the expression // means something very specific, and it might not be what\nyou think. Contrary to common belief, // means \"anywhere in the document\" not \"anywhere\nin the current context\". As an example:\n\n```ruby\npage.find(:xpath, '//body').all(:xpath, '//script')\n```\n\nYou might expect this to find all script tags in the body, but actually, it finds all\nscript tags in the entire document, not only those in the body! What you're looking\nfor is the .// expression which means \"any descendant of the current node\":\n\n```ruby\npage.find(:xpath, '//body').all(:xpath, './/script')\n```\nThe same thing goes for within:\n\n```ruby\nwithin(:xpath, '//body') do\n  page.find(:xpath, './/script')\n  within(:xpath, './/table/tbody') do\n  ...\n  end\nend\n```\n\n## <a name=\"configuring-and-adding-drivers\"></a>Configuring and adding drivers\n\nCapybara makes it convenient to switch between different drivers. It also exposes\nan API to tweak those drivers with whatever settings you want, or to add your own\ndrivers. This is how to override the selenium driver configuration to use chrome:\n\n```ruby\nCapybara.register_driver :selenium do |app|\n  Capybara::Selenium::Driver.new(app, :browser => :chrome)\nend\n```\n\nHowever, it's also possible to give this configuration a different name.\n\n```ruby\n# Note: Capybara registers this by default\nCapybara.register_driver :selenium_chrome do |app|\n  Capybara::Selenium::Driver.new(app, :browser => :chrome)\nend\n```\n\nThen tests can switch between using different browsers effortlessly:\n```ruby\nCapybara.current_driver = :selenium_chrome\n```\n\nWhatever is returned from the block should conform to the API described by\nCapybara::Driver::Base, it does not however have to inherit from this class.\nGems can use this API to add their own drivers to Capybara.\n\nThe [Selenium wiki](https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings) has\nadditional info about how the underlying driver can be configured.\n\n## <a name=\"gotchas\"></a>Gotchas:\n\n* Access to session and request is not possible from the test, Access to\n  response is limited. Some drivers allow access to response headers and HTTP\n  status code, but this kind of functionality is not provided by some drivers,\n  such as Selenium.\n\n* Access to Rails specific stuff (such as `controller`) is unavailable,\n  since we're not using Rails' integration testing.\n\n* Freezing time: It's common practice to mock out the Time so that features\n  that depend on the current Date work as expected. This can be problematic on\n  ruby/platform combinations that don't support access to a monotonic process clock,\n  since Capybara's Ajax timing uses the system time, resulting in Capybara\n  never timing out and just hanging when a failure occurs. It's still possible to\n  use gems which allow you to travel in time, rather than freeze time.\n  One such gem is [Timecop](https://github.com/travisjeffery/timecop).\n\n* When using Rack::Test, beware if attempting to visit absolute URLs. For\n  example, a session might not be shared between visits to `posts_path`\n  and `posts_url`. If testing an absolute URL in an Action Mailer email,\n  set `default_url_options` to match the Rails default of\n  `www.example.com`.\n\n* Server errors will only be raised in the session that initiates the server thread. If you\n  are testing for specific server errors and using multiple sessions make sure to test for the\n  errors using the initial session (usually :default)\n\n* If WebMock is enabled, you may encounter a \"Too many open files\"\n  error. A simple `page.find` call may cause thousands of HTTP requests\n  until the timeout occurs. By default, WebMock will cause each of these\n  requests to spawn a new connection. To work around this problem, you\n  may need to [enable WebMock's `net_http_connect_on_start: true`\n  parameter](https://github.com/bblimke/webmock/blob/master/README.md#connecting-on-nethttpstart).\n\n## <a name=\"threadsafe\"></a>\"Threadsafe\" mode\n\nIn normal mode most of Capybara's configuration options are global settings which can cause issues\nif using multiple sessions and wanting to change a setting for only one of the sessions.  To provide\nsupport for this type of usage Capybara now provides a \"threadsafe\" mode which can be enabled by setting\n\n```ruby\nCapybara.threadsafe = true\n```\n\nThis setting can only be changed before any sessions have been created.  In \"threadsafe\" mode the following\nbehaviors of Capybara change\n\n* Most options can now be set on a session.  These can either be set at session creation time or after, and\n  default to the global options at the time of session creation.  Options which are NOT session specific are\n  `app`, `reuse_server`, `default_driver`, `javascript_driver`, and (obviously) `threadsafe`.  Any drivers and servers\n  registered through `register_driver` and `register_server` are also global.\n\n  ```ruby\n  my_session = Capybara::Session.new(:driver, some_app) do |config|\n    config.automatic_label_click = true # only set for my_session\n  end\n  my_session.config.default_max_wait_time = 10 # only set for my_session\n  Capybara.default_max_wait_time = 2 # will not change the default_max_wait in my_session\n  ```\n\n* `current_driver` and `session_name` are thread specific.  This means that `using_session` and\n  `using_driver` also only affect the current thread.\n\n## <a name=\"development\"></a>Development\n\nTo set up a development environment, simply do:\n\n```bash\nbundle install\nbundle exec rake  # run the test suite with Firefox - requires `geckodriver` to be installed\nbundle exec rake spec_chrome # run the test suite with Chrome - require `chromedriver` to be installed\n```\n\nSee\n[CONTRIBUTING.md](https://github.com/teamcapybara/capybara/blob/master/CONTRIBUTING.md)\nfor how to send issues and pull requests.\n"
  },
  {
    "path": "Rakefile",
    "content": "# frozen_string_literal: true\n\nrequire 'rubygems'\nrequire 'rspec/core/rake_task'\nrequire 'cucumber/rake/task'\nrequire 'yard'\nrequire 'rubocop/rake_task'\n\nRuboCop::RakeTask.new\n\ndesc 'Run all examples with Firefox'\n\nrspec_opts = '--color'\n\nRSpec::Core::RakeTask.new(:spec_firefox) do |t|\n  t.rspec_opts = rspec_opts\n  t.pattern = './spec{,/*/**}/*{_spec.rb,_spec_firefox.rb}'\nend\n\n%w[chrome ie edge chrome_remote firefox_remote safari].each do |driver|\n  desc \"Run tests using #{driver} driver\"\n  RSpec::Core::RakeTask.new(:\"spec_#{driver}\") do |t|\n    t.rspec_opts = rspec_opts\n    t.pattern = \"./spec/{selenium_spec_#{driver}.rb}\"\n  end\nend\n\nRSpec::Core::RakeTask.new(:spec_sauce) do |t|\n  t.rspec_opts = rspec_opts\n  t.pattern = './spec/sauce_spec_chrome.rb'\nend\n\n# RSpec::Core::RakeTask.new(:spec_rack, [] => :rubocop) do |t|\nRSpec::Core::RakeTask.new(:spec_rack) do |t|\n  t.rspec_opts = rspec_opts\n  t.pattern = './spec{,/*/**}/*{_spec.rb}'\nend\n\ndesc 'Run specs with Firefox'\ntask spec: [:spec_firefox]\n\ndesc 'Run basic smoke tests (rack test and rubocop)'\ntask rack_smoke: %i[rubocop spec_rack]\n\nYARD::Rake::YardocTask.new do |t|\n  t.files   = ['lib/**/*.rb']\nend\n\nCucumber::Rake::Task.new(:cucumber) do |task|\n  task.cucumber_opts = ['--format=progress', '--publish-quiet', 'features']\nend\n\ndesc 'Task for running CI'\ntask :travis do\n  if ENV.fetch('CAPYBARA_REMOTE', nil) && ENV.fetch('CAPYBARA_FF', nil)\n    Rake::Task[:spec_firefox_remote].invoke\n  elsif ENV.fetch('CAPYBARA_FF', nil)\n    Rake::Task[:spec_firefox].invoke\n  elsif ENV.fetch('CAPYBARA_IE', nil)\n    Rake::Task[:spec_ie].invoke\n  elsif ENV.fetch('CAPYBARA_EDGE', nil)\n    Rake::Task[:spec_edge].invoke\n  elsif ENV.fetch('CAPYBARA_REMOTE', nil)\n    Rake::Task[:spec_chrome_remote].invoke\n  else\n    Rake::Task[:spec_chrome].invoke\n  end\n  Rake::Task[:cucumber].invoke\nend\n\ndesc 'Build updated JS replacements for Selenium atoms'\ntask :build_js do\n  require 'uglifier'\n  Dir.glob('./lib/capybara/selenium/atoms/src/*.js').each do |fn|\n    js = Uglifier.compile(\n      File.read(fn),\n      compress: {\n        negate_iife: false, # Negate immediately invoked function expressions to avoid extra parens\n        side_effects: false # Pass false to disable potentially dropping functions marked as \"pure\"\n      }\n    )[0...-1]\n    File.write(\"./lib/capybara/selenium/atoms/#{File.basename(fn).gsub('.js', '.min.js')}\", js)\n  end\nend\n\ndesc 'Release new version'\ntask :release do\n  version = Capybara::VERSION\n  puts \"Releasing #{version}, y/n?\"\n  exit(1) unless $stdin.gets.chomp == 'y'\n  sh \"git commit -am 'tagged #{version}' && \" \\\n     \"git tag #{version} && \" \\\n     'gem build capybara.gemspec && ' \\\n     \"gem push capybara-#{version}.gem && \" \\\n     'git push && ' \\\n     'git push --tags'\nend\n\ntask default: %i[spec cucumber]\n"
  },
  {
    "path": "UPGRADING.md",
    "content": "# Upgrading from Capybara 2.x to 3.x\n\n## Server\n\nCapybara 3 changes the default server to <a href=\"https://github.com/puma/puma\">Puma</a>. If you do not use `Puma` in your project you can\nrevert to the previous default of WEBRick by specifying\n\n```ruby\nCapybara.server = :webrick\n```\n\n## Finders\n\nThe biggest user differences between Capybara 2.x and 3.x are the changes in behavior of `first` and `all`. In Capybara 2.x both methods would, by default, return immediately with nil if no matching elements exist on the page.  In Capybara 3.x this has changed to include the waiting/retrying behavior found in the other Capybara finders and matchers.\n\n`first` will now wait up to `Capybara.default_max_wait_time` seconds for at least one matching element to exist, and return the first matching element.  If no matching elements are found within the time it will now raise a `Capybara::ElementNotFound` error instead of returning nil. If you need to maintain the previous behavior you can pass `minimum: 0` as an option to `first`\n\n```ruby\nfirst('div', minimum: 0)\n```\n\n`all` will now wait up to `Capybara.default_max_wait_time` seconds for at least one matching element to exist, and return the matching elements.  If no matching elements are found within the time it will return an empty result set.  If you need to maintain the previous behavior you can pass `wait: false` as an option to `all`\n\n```ruby\nall('div', wait: false)\n```\n\n## Node\n\n`Node#text` no longer fully normalizes whitespace, instead returning text as close as possible to \"as rendered\". This means non-blanking spaces will no longer be collapsed, carriage returns may be returned in text strings, etc.  This affects not only the `Node#text` method but also methods that take a `:text` option as well as the text related predicates, assertions, and matchers (`has_text?`, `has_content?`, `assert_text`, `have_text`, etc.).\n"
  },
  {
    "path": "appveyor.yml.outdated",
    "content": "version: 1.0.{build}-{branch}\n\ncache:\n  - vendor/bundle\n\n# image: Visual Studio 2017\n\nenvironment:\n  matrix:\n    - RUBY_VERSION: 26\n      CAPYBARA_FF: true\n    - RUBY_VERSION: 25\n      CAPYBARA_IE: true\n      BUNDLE_GEMFILE: gemfiles/Gemfile.ie\n    - RUBY_VERSION: 24\n\nmatrix:\n  allow_failures:\n    - CAPYBARA_IE: true\n    - CAPYBARA_EDGE: true\n\ninit:\n  - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/set-screenresolution.ps1'))\n  - ps: Set-ScreenResolution 1600 1200\n  - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))\n\ninstall:\n  - set PATH=C:\\Ruby%RUBY_VERSION%\\bin;%PATH%\n  - cinst Firefox GoogleChrome\n  # Registry hack so driver can maintain connection\n  - REG ADD \"HKLM\\SOFTWARE\\Microsoft\\Internet Explorer\\MAIN\\FeatureControl\\FEATURE_BFCACHE\" /v iexplore.exe /t REG_DWORD /d 00000000\n  - REG ADD \"HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer\\MAIN\\FeatureControl\\FEATURE_BFCACHE\" /v iexplore.exe /t REG_DWORD /d 00000000\n  - bundle config --local path vendor/bundle\n  - bundle install\n\nbuild: off\n\nbefore_test:\n  # - ps: Invoke-WebRequest 'https://github.com/SeleniumHQ/selenium/raw/master/cpp/prebuilt/Win32/Release/IEDriverServer.exe' -OutFile 'C:\\Tools\\WebDriver\\IEDriverServer.exe'\n  - ruby -v\n  - gem -v\n  - bundle -v\n  # - chromedriver.exe --version\n  # - geckodriver.exe --version\n  # - IEDriverServer.exe --version\n\ntest_script:\n  - bundle exec rake travis"
  },
  {
    "path": "capybara.gemspec",
    "content": "# frozen_string_literal: true\n\nlib = File.expand_path('lib', __dir__)\n$:.unshift lib unless $:.include?(lib)\n\nrequire 'capybara/version'\n\nGem::Specification.new do |s|\n  s.name = 'capybara'\n  s.version = Capybara::VERSION\n  s.required_ruby_version = '>= 3.2.0'\n  s.license = 'MIT'\n\n  s.authors = ['Thomas Walpole', 'Jonas Nicklas']\n  s.email = ['twalpole@gmail.com', 'jonas.nicklas@gmail.com']\n  s.description = 'Capybara is an integration testing tool for rack based web applications. ' \\\n                  'It simulates how a user would interact with a website'\n\n  # Test files are included in the gem to allow third-party driver packages to\n  # run the Capybara test suite and ensure compatibility.\n  s.files = Dir.glob('{lib,spec}/**/*') + %w[README.md History.md License.txt .yardopts]\n\n  s.homepage = 'https://github.com/teamcapybara/capybara'\n  s.metadata = {\n    'changelog_uri' => 'https://github.com/teamcapybara/capybara/blob/master/History.md',\n    'source_code_uri' => 'https://github.com/teamcapybara/capybara',\n    'rubygems_mfa_required' => 'true'\n  }\n  s.require_paths = ['lib']\n  s.summary = 'Capybara aims to simplify the process of integration testing Rack applications, ' \\\n              'such as Rails, Sinatra or Merb'\n\n  s.add_runtime_dependency('addressable')\n  s.add_runtime_dependency('matrix')\n  s.add_runtime_dependency('mini_mime', ['>= 0.1.3'])\n  s.add_runtime_dependency('nokogiri', ['~> 1.11'])\n  s.add_runtime_dependency('rack', ['>= 1.6.0'])\n  s.add_runtime_dependency('rack-test', ['>= 0.6.3'])\n  s.add_runtime_dependency('regexp_parser', ['>=1.5', '<3.0'])\n  s.add_runtime_dependency('xpath', ['~>3.2'])\n\n  s.add_development_dependency('byebug') unless RUBY_PLATFORM == 'java'\n  s.add_development_dependency('coveralls')\n  s.add_development_dependency('cucumber', ['>= 2.3.0'])\n  s.add_development_dependency('erubi') # dependency specification needed by rbx\n  s.add_development_dependency('irb')\n  s.add_development_dependency('launchy', ['>= 2.0.4'])\n  s.add_development_dependency('minitest')\n  s.add_development_dependency('puma')\n  s.add_development_dependency('rackup')\n  s.add_development_dependency('rake')\n  s.add_development_dependency('rspec', ['>= 3.5.0'])\n  s.add_development_dependency('rspec-instafail')\n  s.add_development_dependency('rubocop', ['~>1.1'])\n  s.add_development_dependency('rubocop-capybara')\n  s.add_development_dependency('rubocop-minitest')\n  s.add_development_dependency('rubocop-performance')\n  s.add_development_dependency('rubocop-rake')\n  s.add_development_dependency('rubocop-rspec', ['~>3.0'])\n  s.add_development_dependency('sauce_whisk')\n  s.add_development_dependency('selenium_statistics')\n  s.add_development_dependency('selenium-webdriver', ['~>4.8'])\n  s.add_development_dependency('sinatra', ['>= 1.4.0'])\n  s.add_development_dependency('uglifier')\n  s.add_development_dependency('yard', ['>= 0.9.0'])\n\n  if RUBY_ENGINE == 'rbx'\n    s.add_development_dependency('json')\n    s.add_development_dependency('racc')\n    s.add_development_dependency('rubysl')\n  end\n\n  if File.exist?('gem-private_key.pem')\n    s.signing_key = 'gem-private_key.pem'\n    s.cert_chain = ['gem-public_cert.pem']\n  end\nend\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: \"3\"\nservices:\n  selenium_chrome:\n    network_mode: \"host\"\n    image: \"selenium/${SELENIUM_IMAGE:-standalone-chrome}\"\n    volumes:\n      - \"/dev/shm:/dev/shm\"\n  selenium_firefox:\n    network_mode: \"host\"\n    image: \"selenium/${SELENIUM_IMAGE:-standalone-firefox}\"\n    volumes:\n      - \"/dev/shm:/dev/shm\"\n    environment:\n      - SE_OPTS=-port 4445\n"
  },
  {
    "path": "features/capybara.feature",
    "content": "Feature: Capybara's cucumber integration\n  In order to integrate with the lovely plain text testing framework\n  As Capybara\n  I want to integrate successfully with Cucumber\n\n  Scenario: hello world\n    When I visit the root page\n    Then I should see \"Hello world!\"\n\n  @javascript\n  Scenario: javascript tag should use Capybara.javascript_driver\n    When I visit the root page\n    Then Capybara should use the \"javascript_test\" driver\n\n  @named_test\n  Scenario: named driver tag\n    When I visit the root page\n    Then Capybara should use the \"named_test\" driver\n\n  @named_test\n  Scenario Outline: selenium tag with scenario outline\n    When I visit the <Page> page\n    Then Capybara should use the \"named_test\" driver\n\n    Examples:\n      | Page |\n      | root |\n      | home |\n\n  Scenario: matchers\n    When I visit the root page\n    And I use a matcher that fails\n    Then the failing exception should be nice\n"
  },
  {
    "path": "features/named_driver_feature.feature",
    "content": "@named_test\nFeature: an entire feature that uses a driver by tag\n\n  Scenario: should use the named driver without being explicitly told\n    Then Capybara should use the \"named_test\" driver\n"
  },
  {
    "path": "features/step_definitions/capybara_steps.rb",
    "content": "# frozen_string_literal: true\n\nWhen(/^I visit the (?:root|home) page$/) do\n  visit('/')\nend\n\nThen(/^I should see \"([^\"]*)\"$/) do |text|\n  expect(page).to have_content(text)\nend\n\nThen(/^Capybara should use the \"([^\"]*)\" driver$/) do |driver|\n  expect(Capybara.current_driver).to eq(driver.to_sym)\nend\n\nWhen(/^I use a matcher that fails$/) do\n  expect(page).to have_css('h1#doesnotexist')\nrescue StandardError, RSpec::Expectations::ExpectationNotMetError => e\n  @error_message = e.message\nend\n\nThen(/^the failing exception should be nice$/) do\n  expect(@error_message).to match(/expected to find css \"h1#doesnotexist\"/)\nend\n"
  },
  {
    "path": "features/support/env.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rubygems'\nrequire 'bundler/setup'\n\nrequire 'capybara/cucumber'\nrequire 'capybara/spec/test_app'\n\nCapybara.app = TestApp\n\n# These drivers are only used for testing driver switching.\n# They don't actually need to process javascript so use RackTest\n\nCapybara.register_driver :javascript_test do |app|\n  Capybara::RackTest::Driver.new(app)\nend\n\nCapybara.javascript_driver = :javascript_test\n\nCapybara.register_driver :named_test do |app|\n  Capybara::RackTest::Driver.new(app)\nend\n"
  },
  {
    "path": "gem-public_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDPDCCAiSgAwIBAgIBADANBgkqhkiG9w0BAQUFADBEMRYwFAYDVQQDDA1qb25h\ncy5uaWNrbGFzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ\nFgNjb20wHhcNMTMwMjE1MjE1NTM2WhcNMTQwMjE1MjE1NTM2WjBEMRYwFAYDVQQD\nDA1qb25hcy5uaWNrbGFzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ\nk/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb9AZj\ngNdUKIEFktnRTerfYsCqpAFY97qtTbruj4uEKJeyHRLR4FM3sUe4N6Yb48a3JLpA\nHQ1ELh5cSdJdyx8TEXmKscrqEcc2lXSgbkoFpyo6IAcEOSpC9vlAeyGpwkKI/+bP\nbWw3jV236q0Cr7aFMH6nmUvJJsadOwNyUYZWATqOt6X3QoLiEphf7SwhLzAZJr6f\nHhvjJ0Xo2y/LiJj9N0goOhUL6tC5ws5j4wxP8Z+YFY0Q7x7Q6RQBWcCUhc/GAWex\n0eXRj2QOTzVrrIOnPN1jqifnqqU30YoMFMh/e6o3x/ziYMn7zAbFXSbtXDKCK4BT\n3zGZgCiuecspHy9/AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFPb8+DY0\nfm9BZldc/eaKZxfI6XucMAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEA\nJtZrjd9Ds5rcBVP2L9vEa6F2oseq7ye8bavQo9Uh81fDCbVdnaZPhyMth5QhdIBL\npG+uafCMAfgU0vQeNXnAzIxmltnP4+e3IwR0Oe21eUD6lSPSvCoIaQ2eDVxoHPPJ\n5NrJKxj2uuNV1yGLmVhXUFET0OkVvBgdxNmtbE2rRbxXjv5xqW6nBsgVAz0qSxB3\n9yDTZKW7++Em+yFufMlDr7+1rl8cTxv1Kj43Geu5LVz7n/lHYKAdje4uJ3eBtagI\ndwCI6mleXOr4MSRezf19ZUFr0CqlFcrpBSyOakStQLM8La3EAmhOEUa2UE2FIgq5\nR1SH1ni+3bH7B4tAkbWskg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "gemfiles/Gemfile.base-versions",
    "content": "source 'https://rubygems.org'\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'rack', '~>2.0.0'\ngem 'nokogiri', '~>1.11.0'\ngem 'xpath', '~>3.2.0'\ngem 'rspec', '~>3.5.0'\ngem 'selenium-webdriver', '~>4.11.0'\ngem 'irb', '~>1.1.1'\n"
  },
  {
    "path": "gemfiles/Gemfile.beta-versions",
    "content": "source \"https://rubygems.org\"\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'pkg-config' # needed by nokogiri\ngem 'xpath', github: 'teamcapybara/xpath'\ngem 'rack', github: 'rack/rack'\ngem 'sinatra', github: 'sinatra/sinatra', branch: 'master'\ngem 'rspec', github: 'rspec/rspec', branch: 'main'\ngem 'rspec-core', github: 'rspec/rspec-core', branch: 'main'\ngem 'rspec-support', github: 'rspec/rspec-support', branch: 'main'\ngem 'rspec-mocks', github: 'rspec/rspec-mocks', branch: 'main'\ngem 'rspec-expectations', github: 'rspec/rspec-expectations', branch: 'main'\ngem 'cucumber', github: 'cucumber/cucumber-ruby'\ngem 'cucumber-core', github: 'cucumber/cucumber-ruby-core'\ngem 'cucumber-wire', github: 'cucumber/cucumber-ruby-wire'\ngem 'puma', github: 'puma/puma'\ngem 'selenium-webdriver', '>= 4.8.6'\n\n"
  },
  {
    "path": "gemfiles/Gemfile.chrome_edge",
    "content": "source \"https://rubygems.org\"\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'xpath', github: 'teamcapybara/xpath'\n\ngem 'selenium-webdriver', github: 'seleniumhq/selenium', glob: 'rb/*.gemspec'\ngem 'rack', github: 'rack/rack'\ngem 'sinatra', github: 'sinatra/sinatra', branch: 'master'\n\ngem 'puma', github: 'puma/puma'\n"
  },
  {
    "path": "gemfiles/Gemfile.edge-firefox",
    "content": "source \"https://rubygems.org\"\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'xpath', github: 'teamcapybara/xpath'\n\ngem 'selenium-webdriver', '>= 4.8.0'\ngem 'rack', github: 'rack/rack'\ngem 'sinatra', github: 'sinatra/sinatra', branch: 'master'\n\ngem 'puma', github: 'puma/puma'\n"
  },
  {
    "path": "gemfiles/Gemfile.ie",
    "content": "source 'https://rubygems.org'\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n"
  },
  {
    "path": "gemfiles/Gemfile.rack2",
    "content": "source \"https://rubygems.org\"\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'rack', '~>2.0'\ngem 'sinatra', '~>3'"
  },
  {
    "path": "gemfiles/Gemfile.rack3",
    "content": "source \"https://rubygems.org\"\n\ngem 'bundler', '< 3.0'\ngemspec path: '..'\n\ngem 'rack', '~>3.0'\ngem 'rackup'\ngem 'sinatra', '~>4'"
  },
  {
    "path": "lib/capybara/config.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'forwardable'\nrequire 'capybara/session/config'\n\nmodule Capybara\n  class Config\n    extend Forwardable\n\n    OPTIONS = %i[\n      app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo\n    ].freeze\n\n    attr_accessor :app, :use_html5_parsing\n    attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor\n    attr_writer :default_driver, :javascript_driver\n\n    SessionConfig::OPTIONS.each do |method|\n      def_delegators :session_options, method, \"#{method}=\"\n    end\n\n    def initialize\n      @session_options = Capybara::SessionConfig.new\n      @javascript_driver = nil\n    end\n\n    attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor\n\n    def threadsafe=(bool)\n      if (bool != threadsafe) && Session.instance_created?\n        raise 'Threadsafe setting cannot be changed once a session is created'\n      end\n\n      @threadsafe = bool\n    end\n\n    ##\n    #\n    # Return the proc that Capybara will call to run the Rack application.\n    # The block returned receives a rack app, port, and host/ip and should run a Rack handler\n    # By default, Capybara will try to use puma.\n    #\n    attr_reader :server\n\n    ##\n    #\n    # Set the server to use.\n    #\n    #     Capybara.server = :webrick\n    #     Capybara.server = :puma, { Silent: true }\n    #\n    # @overload server=(name)\n    #   @param [Symbol] name     Name of the server type to use\n    # @overload server=([name, options])\n    #   @param [Symbol] name Name of the server type to use\n    #   @param [Hash] options Options to pass to the server block\n    # @see register_server\n    #\n    def server=(name)\n      name, options = *name if name.is_a? Array\n      @server = if name.respond_to? :call\n        name\n      elsif options\n        proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }\n      else\n        Capybara.servers[name.to_sym]\n      end\n    end\n\n    ##\n    #\n    # @return [Symbol]    The name of the driver to use by default\n    #\n    def default_driver\n      @default_driver || :rack_test\n    end\n\n    ##\n    #\n    # @return [Symbol]    The name of the driver used when JavaScript is needed\n    #\n    def javascript_driver\n      @javascript_driver || :selenium\n    end\n\n    def deprecate(method, alternate_method, once: false)\n      @deprecation_notified ||= {}\n      unless once && @deprecation_notified[method]\n        Capybara::Helpers.warn \"DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead: #{Capybara::Helpers.filter_backtrace(caller)}\"\n      end\n      @deprecation_notified[method] = true\n    end\n\n    def allow_gumbo=(val)\n      deprecate('allow_gumbo=', 'use_html5_parsing=')\n      self.use_html5_parsing = val\n    end\n\n    def allow_gumbo\n      deprecate('allow_gumbo', 'use_html5_parsing')\n      use_html5_parsing\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/cucumber.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/dsl'\nrequire 'capybara/rspec/matchers'\nrequire 'capybara/rspec/matcher_proxies'\n\nWorld(Capybara::DSL)\nWorld(Capybara::RSpecMatchers)\n\nAfter do\n  Capybara.reset_sessions!\nend\n\nBefore do\n  Capybara.use_default_driver\nend\n\nBefore '@javascript' do\n  Capybara.current_driver = Capybara.javascript_driver\nend\n\nBefore do |scenario|\n  scenario.source_tag_names.each do |tag|\n    driver_name = tag.sub(/^@/, '').to_sym\n    Capybara.current_driver = driver_name if Capybara.drivers[driver_name]\n  end\nend\n"
  },
  {
    "path": "lib/capybara/driver/base.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::Driver::Base\n  attr_writer :session\n\n  def current_url\n    raise NotImplementedError\n  end\n\n  def visit(path)\n    raise NotImplementedError\n  end\n\n  def refresh\n    raise NotImplementedError\n  end\n\n  def find_xpath(query, **options)\n    raise NotImplementedError\n  end\n\n  def find_css(query, **options)\n    raise NotImplementedError\n  end\n\n  def html\n    raise NotImplementedError\n  end\n\n  def go_back\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#go_back'\n  end\n\n  def go_forward\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#go_forward'\n  end\n\n  def execute_script(script, *args)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#execute_script'\n  end\n\n  def evaluate_script(script, *args)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#evaluate_script'\n  end\n\n  def evaluate_async_script(script, *args)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#evaluate_script_asnyc'\n  end\n\n  def save_screenshot(path, **options)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#save_screenshot'\n  end\n\n  def response_headers\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#response_headers'\n  end\n\n  def status_code\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'\n  end\n\n  def send_keys(*)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys'\n  end\n\n  def active_element\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#active_element'\n  end\n\n  ##\n  #\n  # @param frame [Capybara::Node::Element, :parent, :top]  The iframe element to switch to\n  #\n  def switch_to_frame(frame)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_frame'\n  end\n\n  def frame_title\n    find_xpath('/html/head/title').map(&:all_text).first.to_s\n  end\n\n  def frame_url\n    evaluate_script('document.location.href')\n  rescue Capybara::NotSupportedByDriverError\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#frame_title'\n  end\n\n  def current_window_handle\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#current_window_handle'\n  end\n\n  def window_size(handle)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_size'\n  end\n\n  def resize_window_to(handle, width, height)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#resize_window_to'\n  end\n\n  def maximize_window(handle)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#maximize_window'\n  end\n\n  def fullscreen_window(handle)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#fullscreen_window'\n  end\n\n  def close_window(handle)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#close_window'\n  end\n\n  def window_handles\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_handles'\n  end\n\n  def open_new_window\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#open_new_window'\n  end\n\n  def switch_to_window(handle)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_window'\n  end\n\n  def no_such_window_error\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#no_such_window_error'\n  end\n\n  ##\n  #\n  # Execute the block, and then accept the modal opened.\n  # @param type [:alert, :confirm, :prompt]\n  # @option options [Numeric] :wait  How long to wait for the modal to appear after executing the block.\n  # @option options [String, Regexp] :text  Text to verify is in the message shown in the modal\n  # @option options [String] :with  Text to fill in in the case of a prompt\n  # @return [String]  the message shown in the modal\n  # @raise [Capybara::ModalNotFound]  if modal dialog hasn't been found\n  #\n  def accept_modal(type, **options, &blk)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#accept_modal'\n  end\n\n  ##\n  #\n  # Execute the block, and then dismiss the modal opened.\n  # @param type [:alert, :confirm, :prompt]\n  # @option options [Numeric] :wait  How long to wait for the modal to appear after executing the block.\n  # @option options [String, Regexp] :text  Text to verify is in the message shown in the modal\n  # @return [String]  the message shown in the modal\n  # @raise [Capybara::ModalNotFound]  if modal dialog hasn't been found\n  #\n  def dismiss_modal(type, **options, &blk)\n    raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#dismiss_modal'\n  end\n\n  def invalid_element_errors\n    []\n  end\n\n  def wait?\n    false\n  end\n\n  def reset!; end\n\n  def needs_server?\n    false\n  end\n\n  def session_options\n    session&.config || Capybara.session_options\n  end\n\nprivate\n\n  def session\n    @session ||= nil\n  end\nend\n"
  },
  {
    "path": "lib/capybara/driver/node.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Driver\n    class Node\n      attr_reader :driver, :native, :initial_cache\n\n      def initialize(driver, native, initial_cache = {})\n        @driver = driver\n        @native = native\n        @initial_cache = initial_cache\n      end\n\n      def all_text\n        raise NotImplementedError\n      end\n\n      def visible_text\n        raise NotImplementedError\n      end\n\n      def [](name)\n        raise NotImplementedError\n      end\n\n      def value\n        raise NotImplementedError\n      end\n\n      def style(styles)\n        raise NotImplementedError\n      end\n\n      # @param value [String, Array] Array is only allowed if node has 'multiple' attribute\n      # @param options [Hash] Driver specific options for how to set a value on a node\n      def set(value, **options)\n        raise NotImplementedError\n      end\n\n      def select_option\n        raise NotImplementedError\n      end\n\n      def unselect_option\n        raise NotImplementedError\n      end\n\n      def click(keys = [], **options)\n        raise NotImplementedError\n      end\n\n      def right_click(keys = [], **options)\n        raise NotImplementedError\n      end\n\n      def double_click(keys = [], **options)\n        raise NotImplementedError\n      end\n\n      def send_keys(*args)\n        raise NotImplementedError\n      end\n\n      def hover\n        raise NotImplementedError\n      end\n\n      def drag_to(element, **options)\n        raise NotImplementedError\n      end\n\n      def drop(*args)\n        raise NotImplementedError\n      end\n\n      def scroll_by(x, y)\n        raise NotImplementedError\n      end\n\n      def scroll_to(element, alignment, position = nil)\n        raise NotImplementedError\n      end\n\n      def tag_name\n        raise NotImplementedError\n      end\n\n      def visible?\n        raise NotImplementedError\n      end\n\n      def obscured?\n        raise NotImplementedError\n      end\n\n      def checked?\n        raise NotImplementedError\n      end\n\n      def selected?\n        raise NotImplementedError\n      end\n\n      def disabled?\n        raise NotImplementedError\n      end\n\n      def readonly?\n        !!self[:readonly]\n      end\n\n      def multiple?\n        !!self[:multiple]\n      end\n\n      def rect\n        raise NotSupportedByDriverError, 'Capybara::Driver::Node#rect'\n      end\n\n      def path\n        raise NotSupportedByDriverError, 'Capybara::Driver::Node#path'\n      end\n\n      def trigger(event)\n        raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'\n      end\n\n      def shadow_root\n        raise NotSupportedByDriverError, 'Capybara::Driver::Node#shadow_root'\n      end\n\n      def inspect\n        %(#<#{self.class} tag=\"#{tag_name}\" path=\"#{path}\">)\n      rescue NotSupportedByDriverError\n        %(#<#{self.class} tag=\"#{tag_name}\">)\n      end\n\n      def ==(other)\n        eql?(other) || (other.respond_to?(:native) && native == other.native)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/dsl.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara'\n\nmodule Capybara\n  module DSL\n    def self.included(base)\n      warn 'including Capybara::DSL in the global scope is not recommended!' if base == Object\n      super\n    end\n\n    def self.extended(base)\n      warn 'extending the main object with Capybara::DSL is not recommended!' if base == TOPLEVEL_BINDING.eval('self')\n      super\n    end\n\n    ##\n    #\n    # Shortcut to working in a different session.\n    #\n    def using_session(name_or_session, &block)\n      Capybara.using_session(name_or_session, &block)\n    end\n\n    # Shortcut to using a different wait time.\n    #\n    def using_wait_time(seconds, &block)\n      page.using_wait_time(seconds, &block)\n    end\n\n    ##\n    #\n    # Shortcut to accessing the current session.\n    #\n    #     class MyClass\n    #       include Capybara::DSL\n    #\n    #       def has_header?\n    #         page.has_css?('h1')\n    #       end\n    #     end\n    #\n    # @return [Capybara::Session] The current session object\n    #\n    def page\n      Capybara.current_session\n    end\n\n    Session::DSL_METHODS.each do |method|\n      class_eval <<~METHOD, __FILE__, __LINE__ + 1\n        def #{method}(...)\n          page.method(\"#{method}\").call(...)\n        end\n      METHOD\n    end\n  end\n\n  extend(Capybara::DSL)\nend\n"
  },
  {
    "path": "lib/capybara/helpers.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Helpers\n  module_function\n\n    ##\n    # @deprecated\n    # Normalizes whitespace space by stripping leading and trailing\n    # whitespace and replacing sequences of whitespace characters\n    # with a single space.\n    #\n    # @param [String] text     Text to normalize\n    # @return [String]         Normalized text\n    #\n    def normalize_whitespace(text)\n      Capybara::Helpers.warn 'DEPRECATED: Capybara::Helpers::normalize_whitespace is deprecated, please update your driver'\n      text.to_s.gsub(/[[:space:]]+/, ' ').strip\n    end\n\n    ##\n    #\n    # Escapes any characters that would have special meaning in a regexp\n    # if text is not a regexp\n    #\n    # @param [String] text Text to escape\n    # @param [Boolean] exact (false) Whether or not this should be an exact text match\n    # @param [Fixnum, Boolean, nil] options Options passed to Regexp.new when creating the Regexp\n    # @return [Regexp] Regexp to match the passed in text and options\n    #\n    def to_regexp(text, exact: false, all_whitespace: false, options: nil)\n      return text if text.is_a?(Regexp)\n\n      escaped = Regexp.escape(text)\n      escaped = escaped.gsub('\\\\ ', '[[:blank:]]') if all_whitespace\n      escaped = \"\\\\A#{escaped}\\\\z\" if exact\n      Regexp.new(escaped, options)\n    end\n\n    ##\n    #\n    # Injects a `<base>` tag into the given HTML code, pointing to\n    # {Capybara.configure asset_host}.\n    #\n    # @param [String] html     HTML code to inject into\n    # @param [URL] host (Capybara.asset_host) The host from which assets should be loaded\n    # @return [String]         The modified HTML code\n    #\n    def inject_asset_host(html, host: Capybara.asset_host)\n      if host && Nokogiri::HTML(html).css('base').empty?\n        html.match(/<head[^<]*?>/) do |m|\n          return html.clone.insert m.end(0), \"<base href='#{host}' />\"\n        end\n      end\n      html\n    end\n\n    ##\n    #\n    # A poor man's `pluralize`. Given two declensions, one singular and one\n    # plural, as well as a count, this will pick the correct declension. This\n    # way we can generate grammatically correct error message.\n    #\n    # @param [String] singular     The singular form of the word\n    # @param [String] plural       The plural form of the word\n    # @param [Integer] count       The number of items\n    #\n    def declension(singular, plural, count)\n      count == 1 ? singular : plural\n    end\n\n    def filter_backtrace(trace)\n      return 'No backtrace' unless trace\n\n      filter = %r{lib/capybara/|lib/rspec/|lib/minitest/|delegate.rb}\n      new_trace = trace.take_while { |line| line !~ filter }\n      new_trace = trace.grep_v(filter) if new_trace.empty?\n      new_trace = trace.dup if new_trace.empty?\n\n      new_trace.first.split(':in ', 2).first\n    end\n\n    def warn(message, uplevel: 1)\n      Kernel.warn(message, uplevel: uplevel)\n    end\n\n    if defined?(Process::CLOCK_MONOTONIC_RAW)\n      def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_RAW; end\n    elsif defined?(Process::CLOCK_MONOTONIC_PRECISE)\n      def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_PRECISE; end\n    elsif defined?(Process::CLOCK_MONOTONIC)\n      def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC; end\n    else\n      def monotonic_time; Time.now.to_f; end\n    end\n\n    def timer(expire_in:)\n      Timer.new(expire_in)\n    end\n\n    class Timer\n      def initialize(expire_in)\n        @start = current\n        @expire_in = expire_in\n      end\n\n      def expired?\n        if stalled?\n          raise Capybara::FrozenInTime, 'Time appears to be frozen. Capybara does not work with libraries which freeze time, consider using time travelling instead'\n        end\n\n        current - @start >= @expire_in\n      end\n\n      def stalled?\n        @start == current\n      end\n\n    private\n\n      def current\n        Capybara::Helpers.monotonic_time\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/minitest/spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'minitest/spec'\n\nmodule Capybara\n  module Minitest\n    module Expectations\n      ##\n      # Expectation that there is an ancestor\n      #\n      # @!method must_have_ancestor\n      #   See {Capybara::Node::Matchers#has_ancestor?}\n\n      ##\n      # Expectation that there is button\n      #\n      # @!method must_have_button\n      #   See {Capybara::Node::Matchers#has_button?}\n\n      ##\n      # Expectation that there is no button\n      #\n      # @!method wont_have_button\n      #   See {Capybara::Node::Matchers#has_no_button?}\n\n      ##\n      # Expectation that there is checked_field\n      #\n      # @!method must_have_checked_field\n      #   See {Capybara::Node::Matchers#has_checked_field?}\n\n      ##\n      # Expectation that there is no checked_field\n      #\n      # @!method wont_have_checked_field\n      #   See {Capybara::Node::Matchers#has_no_checked_field?}\n\n      ##\n      # Expectation that there is unchecked_field\n      #\n      # @!method must_have_unchecked_field\n      #   See {Capybara::Node::Matchers#has_unchecked_field?}\n\n      ##\n      # Expectation that there is no unchecked_field\n      #\n      # @!method wont_have_unchecked_field\n      #   See {Capybara::Node::Matchers#has_no_unchecked_field?}\n\n      ##\n      # Expectation that page content does match\n      #\n      # @!method must_have_content\n      #   See {Capybara::Node::Matchers#has_content?}\n\n      ##\n      # Expectation that page content does not match\n      #\n      # @!method wont_have_content\n      #   See {Capybara::Node::Matchers#has_no_content?}\n\n      ##\n      # Expectation that there is css\n      #\n      # @!method must_have_css\n      #   See {Capybara::Node::Matchers#has_css?}\n\n      ##\n      # Expectation that there is no css\n      #\n      # @!method wont_have_css\n      #   See {Capybara::Node::Matchers#has_no_css?}\n\n      ##\n      # Expectation that current path matches\n      #\n      # @!method must_have_current_path\n      #   See {Capybara::SessionMatchers#has_current_path?}\n\n      ##\n      # Expectation that current page does not match\n      #\n      # @!method wont_have_current_path\n      #   See {Capybara::SessionMatchers#has_no_current_path?}\n\n      ##\n      # Expectation that there is field\n      #\n      # @!method must_have_field\n      #   See {Capybara::Node::Matchers#has_field?}\n\n      ##\n      # Expectation that there is no field\n      #\n      # @!method wont_have_field\n      #   See {Capybara::Node::Matchers#has_no_field?}\n\n      ##\n      # Expectation that there is element\n      #\n      # @!method must_have_element\n      #   See {Capybara::Node::Matchers#has_element?}\n\n      ##\n      # Expectation that there is no element\n      #\n      # @!method wont_have_element\n      #   See {Capybara::Node::Matchers#has_no_element?}\n\n      ##\n      # Expectation that there is link\n      #\n      # @!method must_have_link\n      #   See {Capybara::Node::Matchers#has_link?}\n\n      ##\n      # Expectation that there is no link\n      #\n      # @!method wont_have_link\n      #   See {Capybara::Node::Matchers#has_no_link?}\n\n      ##\n      # Expectation that page text does match\n      #\n      # @!method must_have_text\n      #   See {Capybara::Node::Matchers#has_text?}\n\n      ##\n      # Expectation that page text does not match\n      #\n      # @!method wont_have_text\n      #   See {Capybara::Node::Matchers#has_no_text?}\n\n      ##\n      # Expectation that page title does match\n      #\n      # @!method must_have_title\n      #   See {Capybara::Node::DocumentMatchers#has_title?}\n\n      ##\n      # Expectation that page title does not match\n      #\n      # @!method wont_have_title\n      #   See {Capybara::Node::DocumentMatchers#has_no_title?}\n\n      ##\n      # Expectation that there is select\n      #\n      # @!method must_have_select\n      #   See {Capybara::Node::Matchers#has_select?}\n\n      ##\n      # Expectation that there is no select\n      #\n      # @!method wont_have_select\n      #   See {Capybara::Node::Matchers#has_no_select?}\n\n      ##\n      # Expectation that there is a selector\n      #\n      # @!method must_have_selector\n      #   See {Capybara::Node::Matchers#has_selector?}\n\n      ##\n      # Expectation that there is no selector\n      #\n      # @!method wont_have_selector\n      #   See {Capybara::Node::Matchers#has_no_selector?}\n\n      ##\n      # Expectation that all of the provided selectors are present\n      #\n      # @!method must_have_all_of_selectors\n      #   See {Capybara::Node::Matchers#assert_all_of_selectors}\n\n      ##\n      # Expectation that none of the provided selectors are present\n      #\n      # @!method must_have_none_of_selectors\n      #   See {Capybara::Node::Matchers#assert_none_of_selectors}\n\n      ##\n      # Expectation that any of the provided selectors are present\n      #\n      # @!method must_have_any_of_selectors\n      #   See {Capybara::Node::Matchers#assert_any_of_selectors}\n\n      ##\n      # Expectation that there is a sibling\n      #\n      # @!method must_have_sibling\n      #   See {Capybara::Node::Matchers#has_sibling?}\n\n      ##\n      # Expectation that element has style\n      #\n      # @!method must_match_style\n      #   See {Capybara::Node::Matchers#matches_style?}\n\n      ##\n      # Expectation that there is table\n      #\n      # @!method must_have_table\n      #   See {Capybara::Node::Matchers#has_table?}\n\n      ##\n      # Expectation that there is no table\n      #\n      # @!method wont_have_table\n      #   See {Capybara::Node::Matchers#has_no_table?}\n\n      ##\n      # Expectation that there is xpath\n      #\n      # @!method must_have_xpath\n      #   See {Capybara::Node::Matchers#has_xpath?}\n\n      ##\n      # Expectation that there is no xpath\n      #\n      # @!method wont_have_xpath\n      #   See {Capybara::Node::Matchers#has_no_xpath?}\n\n      # This currently doesn't work for Ruby 2.8 due to Minitest not forwarding keyword args separately\n      # %w[text content title current_path].each do |assertion|\n      #   infect_an_assertion \"assert_#{assertion}\", \"must_have_#{assertion}\", :reverse\n      #   infect_an_assertion \"refute_#{assertion}\", \"wont_have_#{assertion}\", :reverse\n      # end\n\n      # rubocop:disable Style/MultilineBlockChain\n      (%w[text content title current_path\n          selector xpath css link button field select table checked_field unchecked_field\n          ancestor sibling].flat_map do |assertion|\n            [%W[assert_#{assertion} must_have_#{assertion}],\n             %W[refute_#{assertion} wont_have_#{assertion}]]\n          end + [%w[assert_all_of_selectors must_have_all_of_selectors],\n                 %w[assert_none_of_selectors must_have_none_of_selectors],\n                 %w[assert_any_of_selectors must_have_any_of_selectors],\n                 %w[assert_matches_style must_match_style]] +\n      %w[selector xpath css].flat_map do |assertion|\n        [%W[assert_matches_#{assertion} must_match_#{assertion}],\n         %W[refute_matches_#{assertion} wont_match_#{assertion}]]\n      end).each do |(meth, new_name)|\n        class_eval <<-ASSERTION, __FILE__, __LINE__ + 1\n          def #{new_name}(...)\n            ::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(...)\n          end\n        ASSERTION\n\n        ::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1\n          def #{new_name}(...)\n            raise \"Calling ##{new_name} outside of test.\" unless ctx\n            ctx.#{meth}(target, ...)\n          end\n        ASSERTION\n      end\n      # rubocop:enable Style/MultilineBlockChain\n\n      ##\n      # @deprecated\n      def must_have_style(...)\n        warn 'must_have_style is deprecated, please use must_match_style'\n        must_match_style(...)\n      end\n    end\n  end\nend\n\nclass Capybara::Session\n  include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']\nend\n\nclass Capybara::Node::Base\n  include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']\nend\n\nclass Capybara::Node::Simple\n  include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']\nend\n"
  },
  {
    "path": "lib/capybara/minitest.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'minitest'\nrequire 'capybara/dsl'\n\nmodule Capybara\n  module Minitest\n    module Assertions\n      ##\n      # Assert text exists\n      #\n      # @!method assert_content\n      # @!method assert_text\n      #   See {Capybara::Node::Matchers#assert_text}\n\n      ##\n      # Assert text does not exist\n      #\n      # @!method refute_content\n      # @!method assert_no_content\n      # @!method refute_text\n      # @!method assert_no_text\n      #   See {Capybara::Node::Matchers#assert_no_text}\n\n      ##\n      # Assertion that page title does match\n      #\n      # @!method assert_title\n      #   See {Capybara::Node::DocumentMatchers#assert_title}\n\n      ##\n      # Assertion that page title does not match\n      #\n      # @!method refute_title\n      # @!method assert_no_title\n      #   See {Capybara::Node::DocumentMatchers#assert_no_title}\n\n      ##\n      # Assertion that current path matches\n      #\n      # @!method assert_current_path\n      #   See {Capybara::SessionMatchers#assert_current_path}\n\n      ##\n      # Assertion that current page does not match\n      #\n      # @!method refute_current_path\n      # @!method assert_no_current_path\n      #   See {Capybara::SessionMatchers#assert_no_current_path}\n\n      %w[text no_text title no_title current_path no_current_path].each do |assertion_name|\n        class_eval <<-ASSERTION, __FILE__, __LINE__ + 1\n          def assert_#{assertion_name}(*args, **kwargs, &optional_filter_block)\n            self.assertions +=1\n            subject, args = determine_subject(args)\n            subject.assert_#{assertion_name}(*args, **kwargs, &optional_filter_block)\n          rescue Capybara::ExpectationNotMet => e\n            raise ::Minitest::Assertion, e.message\n          end\n        ASSERTION\n      end\n\n      alias_method :refute_title, :assert_no_title\n      alias_method :refute_text, :assert_no_text\n      alias_method :refute_content, :refute_text\n      alias_method :refute_current_path, :assert_no_current_path\n      alias_method :assert_content, :assert_text\n      alias_method :assert_no_content, :refute_text\n\n      ##\n      # Assert selector exists on page\n      #\n      # @!method assert_selector\n      #   See {Capybara::Node::Matchers#assert_selector}\n\n      ##\n      # Assert selector does not exist on page\n      #\n      # @!method refute_selector\n      # @!method assert_no_selector\n      #   See {Capybara::Node::Matchers#assert_no_selector}\n\n      ##\n      # Assert element matches selector\n      #\n      # @!method assert_matches_selector\n      #   See {Capybara::Node::Matchers#assert_matches_selector}\n\n      ##\n      # Assert element does not match selector\n      #\n      # @!method refute_matches_selector\n      # @!method assert_not_matches_selector\n      #   See {Capybara::Node::Matchers#assert_not_matches_selector}\n\n      ##\n      # Assert all of the provided selectors exist on page\n      #\n      # @!method assert_all_of_selectors\n      #   See {Capybara::Node::Matchers#assert_all_of_selectors}\n\n      ##\n      # Assert none of the provided selectors exist on page\n      #\n      # @!method assert_none_of_selectors\n      #   See {Capybara::Node::Matchers#assert_none_of_selectors}\n\n      ##\n      # Assert any of the provided selectors exist on page\n      #\n      # @!method assert_any_of_selectors\n      #   See {Capybara::Node::Matchers#assert_any_of_selectors}\n\n      ##\n      # Assert element has the provided CSS styles\n      #\n      # @!method assert_matches_style\n      #   See {Capybara::Node::Matchers#assert_matches_style}\n\n      ##\n      # Assert element has a matching sibling\n      #\n      # @!method assert_sibling\n      #   See {Capybara::Node::Matchers#assert_sibling}\n\n      ##\n      # Assert element does not have a matching sibling\n      #\n      # @!method refute_sibling\n      # @!method assert_no_sibling\n      #   See {Capybara::Node::Matchers#assert_no_sibling}\n\n      ##\n      # Assert element has a matching ancestor\n      #\n      # @!method assert_ancestor\n      #   See {Capybara::Node::Matchers#assert_ancestor}\n\n      ##\n      # Assert element does not have a matching ancestor\n      #\n      # @!method refute_ancestor\n      # @!method assert_no_ancestor\n      #   See {Capybara::Node::Matchers#assert_no_ancestor}\n\n      %w[selector no_selector matches_style\n         all_of_selectors none_of_selectors any_of_selectors\n         matches_selector not_matches_selector\n         sibling no_sibling ancestor no_ancestor].each do |assertion_name|\n        class_eval <<-ASSERTION, __FILE__, __LINE__ + 1\n          def assert_#{assertion_name} *args, &optional_filter_block\n            self.assertions +=1\n            subject, args = determine_subject(args)\n            subject.assert_#{assertion_name}(*args, &optional_filter_block)\n          rescue Capybara::ExpectationNotMet => e\n            raise ::Minitest::Assertion, e.message\n          end\n        ASSERTION\n        ruby2_keywords \"assert_#{assertion_name}\" if respond_to?(:ruby2_keywords)\n      end\n\n      alias_method :refute_selector, :assert_no_selector\n      alias_method :refute_matches_selector, :assert_not_matches_selector\n      alias_method :refute_ancestor, :assert_no_ancestor\n      alias_method :refute_sibling, :assert_no_sibling\n\n      ##\n      # Assert that provided xpath exists\n      #\n      # @!method assert_xpath\n      #   See {Capybara::Node::Matchers#has_xpath?}\n\n      ##\n      # Assert that provide xpath does not exist\n      #\n      # @!method refute_xpath\n      # @!method assert_no_xpath\n      #   See {Capybara::Node::Matchers#has_no_xpath?}\n\n      ##\n      # Assert that provided css exists\n      #\n      # @!method assert_css\n      #   See {Capybara::Node::Matchers#has_css?}\n\n      ##\n      # Assert that provided css does not exist\n      #\n      # @!method refute_css\n      # @!method assert_no_css\n      #   See {Capybara::Node::Matchers#has_no_css?}\n\n      ##\n      # Assert that provided element exists\n      #\n      # @!method assert_element\n      #   See {Capybara::Node::Matchers#has_element?}\n\n      ##\n      # Assert that provided element does not exist\n      #\n      # @!method assert_no_element\n      # @!method refute_element\n      #   See {Capybara::Node::Matchers#has_no_element?}\n\n      ##\n      # Assert that provided link exists\n      #\n      # @!method assert_link\n      #   See {Capybara::Node::Matchers#has_link?}\n\n      ##\n      # Assert that provided link does not exist\n      #\n      # @!method assert_no_link\n      # @!method refute_link\n      #   See {Capybara::Node::Matchers#has_no_link?}\n\n      ##\n      # Assert that provided button exists\n      #\n      # @!method assert_button\n      #   See {Capybara::Node::Matchers#has_button?}\n\n      ##\n      # Assert that provided button does not exist\n      #\n      # @!method refute_button\n      # @!method assert_no_button\n      #   See {Capybara::Node::Matchers#has_no_button?}\n\n      ##\n      # Assert that provided field exists\n      #\n      # @!method assert_field\n      #   See {Capybara::Node::Matchers#has_field?}\n\n      ##\n      # Assert that provided field does not exist\n      #\n      # @!method refute_field\n      # @!method assert_no_field\n      #   See {Capybara::Node::Matchers#has_no_field?}\n\n      ##\n      # Assert that provided checked field exists\n      #\n      # @!method assert_checked_field\n      #   See {Capybara::Node::Matchers#has_checked_field?}\n\n      ##\n      # Assert that provided checked_field does not exist\n      #\n      # @!method assert_no_checked_field\n      # @!method refute_checked_field\n      #   See {Capybara::Node::Matchers#has_no_checked_field?}\n\n      ##\n      # Assert that provided unchecked field exists\n      #\n      # @!method assert_unchecked_field\n      #   See {Capybara::Node::Matchers#has_unchecked_field?}\n\n      ##\n      # Assert that provided unchecked field does not exist\n      #\n      # @!method assert_no_unchecked_field\n      # @!method refute_unchecked_field\n      #   See {Capybara::Node::Matchers#has_no_unchecked_field?}\n\n      ##\n      # Assert that provided select exists\n      #\n      # @!method assert_select\n      #   See {Capybara::Node::Matchers#has_select?}\n\n      ##\n      # Assert that provided select does not exist\n      #\n      # @!method refute_select\n      # @!method assert_no_select\n      #   See {Capybara::Node::Matchers#has_no_select?}\n\n      ##\n      # Assert that provided table exists\n      #\n      # @!method assert_table\n      #   See {Capybara::Node::Matchers#has_table?}\n\n      ##\n      # Assert that provided table does not exist\n      #\n      # @!method refute_table\n      # @!method assert_no_table\n      #   See {Capybara::Node::Matchers#has_no_table?}\n\n      %w[xpath css element link button field select table].each do |selector_type|\n        define_method \"assert_#{selector_type}\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          locator, options = extract_locator(args)\n          assert_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)\n        end\n        ruby2_keywords \"assert_#{selector_type}\" if respond_to?(:ruby2_keywords)\n\n        define_method \"assert_no_#{selector_type}\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          locator, options = extract_locator(args)\n          assert_no_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)\n        end\n        ruby2_keywords \"assert_no_#{selector_type}\" if respond_to?(:ruby2_keywords)\n        alias_method \"refute_#{selector_type}\", \"assert_no_#{selector_type}\"\n      end\n\n      %w[checked unchecked].each do |field_type|\n        define_method \"assert_#{field_type}_field\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          locator, options = extract_locator(args)\n          assert_selector(subject, :field, locator, **options.merge(field_type.to_sym => true), &optional_filter_block)\n        end\n        ruby2_keywords \"assert_#{field_type}_field\" if respond_to?(:ruby2_keywords)\n\n        define_method \"assert_no_#{field_type}_field\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          locator, options = extract_locator(args)\n          assert_no_selector(\n            subject,\n            :field,\n            locator,\n            **options.merge(field_type.to_sym => true),\n            &optional_filter_block\n          )\n        end\n        ruby2_keywords \"assert_no_#{field_type}_field\" if respond_to?(:ruby2_keywords)\n        alias_method \"refute_#{field_type}_field\", \"assert_no_#{field_type}_field\"\n      end\n\n      ##\n      # Assert that element matches xpath\n      #\n      # @!method assert_matches_xpath\n      #   See {Capybara::Node::Matchers#matches_xpath?}\n\n      ##\n      # Assert that element does not match xpath\n      #\n      # @!method refute_matches_xpath\n      # @!method assert_not_matches_xpath\n      #   See {Capybara::Node::Matchers#not_matches_xpath?}\n\n      ##\n      # Assert that element matches css\n      #\n      # @!method assert_matches_css\n      #   See {Capybara::Node::Matchers#matches_css?}\n\n      ##\n      # Assert that element matches css\n      #\n      # @!method refute_matches_css\n      # @!method assert_not_matches_css\n      #   See {Capybara::Node::Matchers#not_matches_css?}\n\n      %w[xpath css].each do |selector_type|\n        define_method \"assert_matches_#{selector_type}\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          assert_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)\n        end\n        ruby2_keywords \"assert_matches_#{selector_type}\" if respond_to?(:ruby2_keywords)\n\n        define_method \"assert_not_matches_#{selector_type}\" do |*args, &optional_filter_block|\n          subject, args = determine_subject(args)\n          assert_not_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)\n        end\n        ruby2_keywords \"assert_not_matches_#{selector_type}\" if respond_to?(:ruby2_keywords)\n        alias_method \"refute_matches_#{selector_type}\", \"assert_not_matches_#{selector_type}\"\n      end\n\n    private\n\n      def determine_subject(args)\n        case args.first\n        when Capybara::Session, Capybara::Node::Base, Capybara::Node::Simple\n          [args.shift, args]\n        when ->(arg) { arg.respond_to?(:to_capybara_node) }\n          [args.shift.to_capybara_node, args]\n        else\n          [page, args]\n        end\n      end\n\n      def extract_locator(args)\n        locator, options = *args, {}\n        locator, options = nil, locator if locator.is_a? Hash\n        [locator, options]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/actions.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    module Actions\n      # @!macro waiting_behavior\n      #   If the driver is capable of executing JavaScript, this method will wait for a set amount of time\n      #   and continuously retry finding the element until either the element is found or the time\n      #   expires. The length of time this method will wait is controlled through {Capybara.configure default_max_wait_time}.\n      #\n      #   @option options [false, true, Numeric] wait\n      #     Maximum time to wait for matching element to appear. Defaults to {Capybara.configure default_max_wait_time}.\n\n      ##\n      #\n      # Finds a button or link and clicks it. See {#click_button} and\n      # {#click_link} for what locator will match against for each type of element.\n      #\n      # @overload click_link_or_button([locator], **options)\n      #   @macro waiting_behavior\n      #   @param [String] locator      See {#click_button} and {#click_link}\n      #\n      # @return [Capybara::Node::Element]  The element clicked\n      #\n      def click_link_or_button(locator = nil, **options)\n        find(:link_or_button, locator, **options).click\n      end\n      alias_method :click_on, :click_link_or_button\n\n      ##\n      #\n      # Finds a link by id, {Capybara.configure test_id} attribute, text or title and clicks it. Also looks at image\n      # alt text inside the link.\n      #\n      # @overload click_link([locator], **options)\n      #   @macro waiting_behavior\n      #   @param [String] locator         text, id, {Capybara.configure test_id} attribute, title or nested image's alt attribute\n      #   @param [Hash] options           See {Capybara::Node::Finders#find_link}\n      #\n      # @return [Capybara::Node::Element]  The element clicked\n      def click_link(locator = nil, **options)\n        find(:link, locator, **options).click\n      end\n\n      ##\n      #\n      # Finds a button on the page and clicks it.\n      # This can be any `<input>` element of type submit, reset, image, button or it can be a\n      # `<button>` element. All buttons can be found by their id, name, {Capybara.configure test_id} attribute, value, or title. `<button>` elements can also be found\n      # by their text content, and image `<input>` elements by their alt attribute.\n      #\n      # @overload click_button([locator], **options)\n      #   @macro waiting_behavior\n      #   @param [String] locator      Which button to find\n      #   @param [Hash] options        See {Capybara::Node::Finders#find_button}\n      # @return [Capybara::Node::Element]  The element clicked\n      def click_button(locator = nil, **options)\n        find(:button, locator, **options).click\n      end\n\n      ##\n      #\n      # Locate a text field or text area and fill it in with the given text.\n      # The field can be found via its name, id, {Capybara.configure test_id} attribute, placeholder, or label text.\n      # If no locator is provided this will operate on self or a descendant.\n      #\n      #     # will fill in a descendant fillable field with name, id, or label text matching 'Name'\n      #     page.fill_in 'Name', with: 'Bob'\n      #\n      #     # will fill in `el` if it's a fillable field\n      #     el.fill_in with: 'Tom'\n      #\n      #\n      # @overload fill_in([locator], with:, **options)\n      #   @param [String] locator                 Which field to fill in\n      #   @param [Hash] options\n      #   @param with: [String]                  The value to fill in\n      #   @macro waiting_behavior\n      #   @option options [String] currently_with The current value property of the field to fill in\n      #   @option options [Boolean] multiple      Match fields that can have multiple values?\n      #   @option options [String, Regexp] id             Match fields that match the id attribute\n      #   @option options [String] name           Match fields that match the name attribute\n      #   @option options [String] placeholder    Match fields that match the placeholder attribute\n      #   @option options [String, Array<String>, Regexp] class    Match fields that match the class(es) provided\n      #   @option options [Hash] fill_options     Driver specific options regarding how to fill fields (Defaults come from {Capybara.configure default_set_options})\n      #\n      # @return [Capybara::Node::Element]  The element filled in\n      def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)\n        find_options[:with] = currently_with if currently_with\n        find_options[:allow_self] = true if locator.nil?\n        find(:fillable_field, locator, **find_options).set(with, **fill_options)\n      end\n\n      # @!macro label_click\n      #   @option options [Boolean, Hash] allow_label_click\n      #     Attempt to click the label to toggle state if element is non-visible. Defaults to {Capybara.configure automatic_label_click}.\n      #     If set to a Hash it is passed as options to the `click` on the label\n\n      ##\n      #\n      # Find a descendant radio button and mark it as checked. The radio button can be found\n      # via name, id, {Capybara.configure test_id} attribute or label text. If no locator is\n      # provided this will match against self or a descendant.\n      #\n      #     # will choose a descendant radio button with a name, id, or label text matching 'Male'\n      #     page.choose('Male')\n      #\n      #     # will choose `el` if it's a radio button element\n      #     el.choose()\n      #\n      # @overload choose([locator], **options)\n      #   @param [String] locator           Which radio button to choose\n      #\n      #   @option options [String] option  Value of the radio_button to choose\n      #   @option options [String, Regexp] id             Match fields that match the id attribute\n      #   @option options [String] name           Match fields that match the name attribute\n      #   @option options [String, Array<String>, Regexp] class    Match fields that match the class(es) provided\n      #   @macro waiting_behavior\n      #   @macro label_click\n      #\n      # @return [Capybara::Node::Element]  The element chosen or the label clicked\n      def choose(locator = nil, **options)\n        _check_with_label(:radio_button, true, locator, **options)\n      end\n\n      ##\n      #\n      # Find a descendant check box and mark it as checked. The check box can be found\n      # via name, id, {Capybara.configure test_id} attribute, or label text. If no locator\n      # is provided this will match against self or a descendant.\n      #\n      #     # will check a descendant checkbox with a name, id, or label text matching 'German'\n      #     page.check('German')\n      #\n      #     # will check `el` if it's a checkbox element\n      #     el.check()\n      #\n      #\n      # @overload check([locator], **options)\n      #   @param [String] locator           Which check box to check\n      #\n      #   @option options [String] option  Value of the checkbox to select\n      #   @option options [String, Regexp] id       Match fields that match the id attribute\n      #   @option options [String] name     Match fields that match the name attribute\n      #   @option options [String, Array<String>, Regexp] class    Match fields that match the class(es) provided\n      #   @macro label_click\n      #   @macro waiting_behavior\n      #\n      # @return [Capybara::Node::Element]  The element checked or the label clicked\n      def check(locator = nil, **options)\n        _check_with_label(:checkbox, true, locator, **options)\n      end\n\n      ##\n      #\n      # Find a descendant check box and uncheck it. The check box can be found\n      # via name, id, {Capybara.configure test_id} attribute, or label text. If\n      # no locator is provided this will match against self or a descendant.\n      #\n      #     # will uncheck a descendant checkbox with a name, id, or label text matching 'German'\n      #     page.uncheck('German')\n      #\n      #     # will uncheck `el` if it's a checkbox element\n      #     el.uncheck()\n      #\n      #\n      # @overload uncheck([locator], **options)\n      #   @param [String] locator           Which check box to uncheck\n      #\n      #   @option options [String] option  Value of the checkbox to deselect\n      #   @option options [String, Regexp] id       Match fields that match the id attribute\n      #   @option options [String] name     Match fields that match the name attribute\n      #   @option options [String, Array<String>, Regexp] class    Match fields that match the class(es) provided\n      #   @macro label_click\n      #   @macro waiting_behavior\n      #\n      # @return [Capybara::Node::Element]  The element unchecked or the label clicked\n      def uncheck(locator = nil, **options)\n        _check_with_label(:checkbox, false, locator, **options)\n      end\n\n      ##\n      #\n      # If `from` option is present, {#select} finds a select box, or text input with associated datalist,\n      # on the page and selects a particular option from it.\n      # Otherwise it finds an option inside current scope and selects it.\n      # If the select box is a multiple select, {#select} can be called multiple times to select more than\n      # one option.\n      # The select box can be found via its name, id, {Capybara.configure test_id} attribute, or label text.\n      # The option can be found by its text.\n      #\n      #     page.select 'March', from: 'Month'\n      #\n      # @overload select(value = nil, from: nil, **options)\n      #   @macro waiting_behavior\n      #\n      #   @param value [String] Which option to select\n      #   @param from [String]  The id, {Capybara.configure test_id} attribute, name or label of the select box\n      #\n      # @return [Capybara::Node::Element]  The option element selected\n      def select(value = nil, from: nil, **options)\n        raise ArgumentError, 'The :from option does not take an element' if from.is_a? Capybara::Node::Element\n\n        el = from ? find_select_or_datalist_input(from, options) : self\n\n        if el.respond_to?(:tag_name) && (el.tag_name == 'input')\n          select_datalist_option(el, value)\n        else\n          el.find(:option, value, **options).select_option\n        end\n      end\n\n      ##\n      #\n      # Find a select box on the page and unselect a particular option from it. If the select\n      # box is a multiple select, {#unselect} can be called multiple times to unselect more than\n      # one option. The select box can be found via its name, id, {Capybara.configure test_id} attribute,\n      # or label text.\n      #\n      #     page.unselect 'March', from: 'Month'\n      #\n      # @overload unselect(value = nil, from: nil, **options)\n      #   @macro waiting_behavior\n      #\n      #   @param value [String]     Which option to unselect\n      #   @param from [String]      The id, {Capybara.configure test_id} attribute, name or label of the select box\n      #\n      #\n      # @return [Capybara::Node::Element]  The option element unselected\n      def unselect(value = nil, from: nil, **options)\n        raise ArgumentError, 'The :from option does not take an element' if from.is_a? Capybara::Node::Element\n\n        scope = from ? find(:select, from, **options) : self\n        scope.find(:option, value, **options).unselect_option\n      end\n\n      ##\n      #\n      # Find a descendant file field on the page and attach a file given its path. There are two ways to use\n      # {#attach_file}, in the first method the file field can be found via its name, id,\n      # {Capybara.configure test_id} attribute, or label text. In the case of the file field being hidden for\n      # styling reasons the `make_visible` option can be used to temporarily change the CSS of\n      # the file field, attach the file, and then revert the CSS back to original. If no locator is\n      # passed this will match self or a descendant.\n      # The second method, which is currently in beta and may be changed/removed, involves passing a block\n      # which performs whatever actions would trigger the file chooser to appear.\n      #\n      #     # will attach file to a descendant file input element that has a name, id, or label_text matching 'My File'\n      #     page.attach_file('My File', '/path/to/file.png')\n      #\n      #     # will attach file to el if it's a file input element\n      #     el.attach_file('/path/to/file.png')\n      #\n      #     # will attach file to whatever file input is triggered by the block\n      #     page.attach_file('/path/to/file.png') do\n      #       page.find('#upload_button').click\n      #     end\n      #\n      # @overload attach_file([locator], paths, **options)\n      #   @macro waiting_behavior\n      #\n      #   @param [String] locator                  Which field to attach the file to\n      #   @param [String, Array<String>] paths     The path(s) of the file(s) that will be attached\n      #\n      #   @option options [Symbol] match\n      #     The matching strategy to use (:one, :first, :prefer_exact, :smart). Defaults to {Capybara.configure match}.\n      #   @option options [Boolean] exact\n      #     Match the exact label name/contents or accept a partial match. Defaults to {Capybara.configure exact}.\n      #   @option options [Boolean] multiple Match field which allows multiple file selection\n      #   @option options [String, Regexp] id             Match fields that match the id attribute\n      #   @option options [String] name           Match fields that match the name attribute\n      #   @option options [String, Array<String>, Regexp] class    Match fields that match the class(es) provided\n      #   @option options [true, Hash] make_visible\n      #     A Hash of CSS styles to change before attempting to attach the file, if `true`, `{ opacity: 1, display: 'block', visibility: 'visible' }` is used (may not be supported by all drivers).\n      # @overload attach_file(paths, &blk)\n      #   @param [String, Array<String>] paths     The path(s) of the file(s) that will be attached\n      #   @yield Block whose actions will trigger the system file chooser to be shown\n      # @return [Capybara::Node::Element]  The file field element\n      def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments\n        if locator && block_given?\n          raise ArgumentError, '`#attach_file` does not support passing both a locator and a block'\n        end\n\n        Array(paths).each do |path|\n          raise Capybara::FileNotFound, \"cannot attach file, #{path} does not exist\" unless File.exist?(path.to_s)\n        end\n        options[:allow_self] = true if locator.nil?\n\n        if block_given?\n          begin\n            execute_script CAPTURE_FILE_ELEMENT_SCRIPT\n            yield\n            file_field = evaluate_script 'window._capybara_clicked_file_input'\n            raise ArgumentError, \"Capybara was unable to determine the file input you're attaching to\" unless file_field\n          rescue ::Capybara::NotSupportedByDriverError\n            warn 'Block mode of `#attach_file` is not supported by the current driver - ignoring.'\n          end\n        end\n        # Allow user to update the CSS style of the file input since they are so often hidden on a page\n        if make_visible\n          ff = file_field || find(:file_field, locator, **options.merge(visible: :all))\n          while_visible(ff, make_visible) { |el| el.set(paths) }\n        else\n          (file_field || find(:file_field, locator, **options)).set(paths)\n        end\n      end\n\n    private\n\n      def find_select_or_datalist_input(from, options)\n        synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do\n          find(:select, from, **options)\n        rescue Capybara::ElementNotFound => select_error # rubocop:disable Naming/RescuedExceptionsVariableName\n          raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }\n\n          begin\n            find(:datalist_input, from, **options)\n          rescue Capybara::ElementNotFound => dlinput_error\n            raise Capybara::ElementNotFound, \"#{select_error.message} and #{dlinput_error.message}\"\n          end\n        end\n      end\n\n      def select_datalist_option(input, value)\n        datalist_options = input.evaluate_script(DATALIST_OPTIONS_SCRIPT)\n        option = datalist_options.find { |opt| opt.values_at('value', 'label').include?(value) }\n        raise ::Capybara::ElementNotFound, %(Unable to find datalist option \"#{value}\") unless option\n\n        input.set(option['value'])\n      rescue ::Capybara::NotSupportedByDriverError\n        # Implement for drivers that don't support JS\n        datalist = find(:xpath, XPath.descendant(:datalist)[XPath.attr(:id) == input[:list]], visible: false)\n        option = datalist.find(:datalist_option, value, disabled: false)\n        input.set(option.value)\n      end\n\n      def while_visible(element, visible_css)\n        if visible_css == true\n          visible_css = { opacity: 1, display: 'block', visibility: 'visible', width: 'auto', height: 'auto' }\n        end\n        _update_style(element, visible_css)\n        unless element.visible?\n          raise ExpectationNotMet, 'The style changes in :make_visible did not make the file input visible'\n        end\n\n        begin\n          yield element\n        ensure\n          _reset_style(element)\n        end\n      end\n\n      def _update_style(element, style)\n        element.execute_script(UPDATE_STYLE_SCRIPT, style)\n      rescue Capybara::NotSupportedByDriverError\n        warn 'The :make_visible option is not supported by the current driver - ignoring'\n      end\n\n      def _reset_style(element)\n        element.execute_script(RESET_STYLE_SCRIPT)\n      rescue StandardError # rubocop:disable Lint/SuppressedException -- swallow extra errors\n      end\n\n      def _check_with_label(selector, checked, locator,\n                            allow_label_click: session_options.automatic_label_click, **options)\n        options[:allow_self] = true if locator.nil?\n        synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do\n          el = find(selector, locator, **options)\n          el.set(checked)\n        rescue StandardError => e\n          raise unless allow_label_click && catch_error?(e)\n\n          begin\n            el ||= find(selector, locator, **options.merge(visible: :all))\n            unless el.checked? == checked\n              el.session\n                .find(:label, for: el, visible: true, match: :first)\n                .click(**(Hash.try_convert(allow_label_click) || {}))\n            end\n          rescue StandardError # swallow extra errors - raise original\n            raise e\n          end\n        end\n      end\n\n      UPDATE_STYLE_SCRIPT = <<~JS\n        this.capybara_style_cache = this.style.cssText;\n        var css = arguments[0];\n        for (var prop in css){\n          if (css.hasOwnProperty(prop)) {\n            this.style.setProperty(prop, css[prop], \"important\");\n          }\n        }\n      JS\n\n      RESET_STYLE_SCRIPT = <<~JS\n        if (this.hasOwnProperty('capybara_style_cache')) {\n          this.style.cssText = this.capybara_style_cache;\n          delete this.capybara_style_cache;\n        }\n      JS\n\n      DATALIST_OPTIONS_SCRIPT = <<~JS\n        Array.prototype.slice.call((this.list||{}).options || []).\n          filter(function(el){ return !el.disabled }).\n          map(function(el){ return { \"value\": el.value, \"label\": el.label} })\n      JS\n\n      CAPTURE_FILE_ELEMENT_SCRIPT = <<~JS\n        document.addEventListener('click', function file_catcher(e){\n          if (e.target.matches(\"input[type='file']\")) {\n            window._capybara_clicked_file_input = e.target;\n            this.removeEventListener('click', file_catcher);\n            e.preventDefault();\n          }\n        }, {capture: true})\n      JS\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    ##\n    #\n    # A {Capybara::Node::Base} represents either an element on a page through the subclass\n    # {Capybara::Node::Element} or a document through {Capybara::Node::Document}.\n    #\n    # Both types of Node share the same methods, used for interacting with the\n    # elements on the page. These methods are divided into three categories,\n    # finders, actions and matchers. These are found in the modules\n    # {Capybara::Node::Finders}, {Capybara::Node::Actions} and {Capybara::Node::Matchers}\n    # respectively.\n    #\n    # A {Capybara::Session} exposes all methods from {Capybara::Node::Document} directly:\n    #\n    #     session = Capybara::Session.new(:rack_test, my_app)\n    #     session.visit('/')\n    #     session.fill_in('Foo', with: 'Bar')    # from Capybara::Node::Actions\n    #     bar = session.find('#bar')                # from Capybara::Node::Finders\n    #     bar.select('Baz', from: 'Quox')        # from Capybara::Node::Actions\n    #     session.has_css?('#foobar')               # from Capybara::Node::Matchers\n    #\n    class Base\n      attr_reader :session, :base, :query_scope\n\n      include Capybara::Node::Finders\n      include Capybara::Node::Actions\n      include Capybara::Node::Matchers\n\n      def initialize(session, base)\n        @session = session\n        @base = base\n      end\n\n      # overridden in subclasses, e.g. Capybara::Node::Element\n      def reload\n        self\n      end\n\n      ##\n      #\n      # This method is Capybara's primary defence against asynchronicity\n      # problems. It works by attempting to run a given block of code until it\n      # succeeds. The exact behaviour of this method depends on a number of\n      # factors. Basically there are certain exceptions which, when raised\n      # from the block, instead of bubbling up, are caught, and the block is\n      # re-run.\n      #\n      # Certain drivers, such as RackTest, have no support for asynchronous\n      # processes, these drivers run the block, and any error raised bubbles up\n      # immediately. This allows faster turn around in the case where an\n      # expectation fails.\n      #\n      # Only exceptions that are {Capybara::ElementNotFound} or any subclass\n      # thereof cause the block to be rerun. Drivers may specify additional\n      # exceptions which also cause reruns. This usually occurs when a node is\n      # manipulated which no longer exists on the page. For example, the\n      # Selenium driver specifies\n      # `Selenium::WebDriver::Error::ObsoleteElementError`.\n      #\n      # As long as any of these exceptions are thrown, the block is re-run,\n      # until a certain amount of time passes. The amount of time defaults to\n      # {Capybara.default_max_wait_time} and can be overridden through the `seconds`\n      # argument. This time is compared with the system time to see how much\n      # time has passed. On rubies/platforms which don't support access to a monotonic process clock\n      # if the return value of `Time.now` is stubbed out, Capybara will raise `Capybara::FrozenInTime`.\n      #\n      # @param  [Integer] seconds  (current sessions default_max_wait_time) Maximum number of seconds to retry this block\n      # @param  [Array<Exception>] errors (driver.invalid_element_errors +\n      #   [Capybara::ElementNotFound]) exception types that cause the block to be rerun\n      # @return [Object]                  The result of the given block\n      # @raise  [Capybara::FrozenInTime]  If the return value of `Time.now` appears stuck\n      #\n      def synchronize(seconds = nil, errors: nil)\n        return yield if session.synchronized\n\n        seconds = session_options.default_max_wait_time if [nil, true].include? seconds\n        interval = session_options.default_retry_interval\n        session.synchronized = true\n        timer = Capybara::Helpers.timer(expire_in: seconds)\n        begin\n          yield\n        rescue StandardError => e\n          session.raise_server_error!\n          raise e unless catch_error?(e, errors)\n\n          if driver.wait?\n            raise e if timer.expired?\n\n            sleep interval\n            reload if session_options.automatic_reload\n          else\n            old_base = @base\n            reload if session_options.automatic_reload\n            raise e if old_base == @base\n          end\n          retry\n        ensure\n          session.synchronized = false\n        end\n      end\n\n      # @api private\n      def find_css(css, **options)\n        if base.method(:find_css).arity == 1\n          base.find_css(css)\n        else\n          base.find_css(css, **options)\n        end\n      end\n\n      # @api private\n      def find_xpath(xpath, **options)\n        if base.method(:find_xpath).arity == 1\n          base.find_xpath(xpath)\n        else\n          base.find_xpath(xpath, **options)\n        end\n      end\n\n      # @api private\n      def session_options\n        session.config\n      end\n\n      def to_capybara_node\n        self\n      end\n\n    protected\n\n      def catch_error?(error, errors = nil)\n        errors ||= (driver.invalid_element_errors + [Capybara::ElementNotFound])\n        errors.any? { |type| error.is_a?(type) }\n      end\n\n      def driver\n        session.driver\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/document.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    ##\n    #\n    # A {Capybara::Document} represents an HTML document. Any operation\n    # performed on it will be performed on the entire document.\n    #\n    # @see Capybara::Node\n    #\n    class Document < Base\n      include Capybara::Node::DocumentMatchers\n\n      def inspect\n        %(#<Capybara::Document>)\n      end\n\n      ##\n      #\n      # @return [String]    The text of the document\n      #\n      def text(type = nil, normalize_ws: false)\n        find(:xpath, '/html').text(type, normalize_ws: normalize_ws)\n      end\n\n      ##\n      #\n      # @return [String]    The title of the document\n      #\n      def title\n        session.driver.title\n      end\n\n      def execute_script(*args)\n        find(:xpath, '/html').execute_script(*args)\n      end\n\n      def evaluate_script(*args)\n        find(:xpath, '/html').evaluate_script(*args)\n      end\n\n      def scroll_to(*args, quirks: false, **options)\n        find(:xpath, quirks ? '//body' : '/html').scroll_to(*args, **options)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/document_matchers.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    module DocumentMatchers\n      ##\n      # Asserts that the page has the given title.\n      #\n      # @!macro title_query_params\n      #   @overload $0(string, **options)\n      #     @param string [String]           The string that title should include\n      #   @overload $0(regexp, **options)\n      #     @param regexp [Regexp]           The regexp that title should match to\n      #   @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for title to eq/match given string/regexp argument\n      #   @option options [Boolean] :exact (false) When passed a string should the match be exact or just substring\n      # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n      # @return [true]\n      #\n      def assert_title(title, **options)\n        _verify_title(title, options) do |query|\n          raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)\n        end\n      end\n\n      ##\n      # Asserts that the page doesn't have the given title.\n      #\n      # @macro title_query_params\n      # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n      # @return [true]\n      #\n      def assert_no_title(title, **options)\n        _verify_title(title, options) do |query|\n          raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)\n        end\n      end\n\n      ##\n      # Checks if the page has the given title.\n      #\n      # @macro title_query_params\n      # @return [Boolean]\n      #\n      def has_title?(title, **options)\n        make_predicate(options) { assert_title(title, **options) }\n      end\n\n      ##\n      # Checks if the page doesn't have the given title.\n      #\n      # @macro title_query_params\n      # @return [Boolean]\n      #\n      def has_no_title?(title, **options)\n        make_predicate(options) { assert_no_title(title, **options) }\n      end\n\n    private\n\n      def _verify_title(title, options)\n        query = Capybara::Queries::TitleQuery.new(title, **options)\n        synchronize(query.wait) { yield(query) }\n        true\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/element.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    ##\n    #\n    # A {Capybara::Node::Element} represents a single element on the page. It is possible\n    # to interact with the contents of this element the same as with a document:\n    #\n    #     session = Capybara::Session.new(:rack_test, my_app)\n    #\n    #     bar = session.find('#bar')              # from Capybara::Node::Finders\n    #     bar.select('Baz', from: 'Quox')      # from Capybara::Node::Actions\n    #\n    # {Capybara::Node::Element} also has access to HTML attributes and other properties of the\n    # element:\n    #\n    #      bar.value\n    #      bar.text\n    #      bar[:title]\n    #\n    # @see Capybara::Node\n    #\n    class Element < Base\n      def initialize(session, base, query_scope, query)\n        super(session, base)\n        @query_scope = query_scope\n        @query = query\n        @allow_reload = false\n        @query_idx = nil\n      end\n\n      def allow_reload!(idx = nil)\n        @query_idx = idx\n        @allow_reload = true\n      end\n\n      ##\n      #\n      # @return [Object]    The native element from the driver, this allows access to driver specific methods\n      #\n      def native\n        synchronize { base.native }\n      end\n\n      ##\n      #\n      # Retrieve the text of the element. If {Capybara.configure ignore_hidden_elements}\n      # is `true`, which it is by default, then this will return only text\n      # which is visible. The exact semantics of this may differ between\n      # drivers, but generally any text within elements with `display:none` is\n      # ignored. This behaviour can be overridden by passing `:all` to this\n      # method.\n      #\n      # @param type [:all, :visible]  Whether to return only visible or all text\n      # @return [String]              The text of the element\n      #\n      def text(type = nil, normalize_ws: false)\n        type ||= :all unless session_options.ignore_hidden_elements || session_options.visible_text_only\n        txt = synchronize { type == :all ? base.all_text : base.visible_text }\n        normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt\n      end\n\n      ##\n      #\n      # Retrieve the given attribute.\n      #\n      #     element[:title] # => HTML title attribute\n      #\n      # @param  [Symbol] attribute     The attribute to retrieve\n      # @return [String]               The value of the attribute\n      #\n      def [](attribute)\n        synchronize { base[attribute] }\n      end\n\n      ##\n      #\n      # Retrieve the given CSS styles.\n      #\n      #     element.style('color', 'font-size') # => Computed values of CSS 'color' and 'font-size' styles\n      #\n      # @param [Array<String>] styles   Names of the desired CSS properties\n      # @return [Hash]            Hash of the CSS property names to computed values\n      #\n      def style(*styles)\n        styles = styles.flatten.map(&:to_s)\n        raise ArgumentError, 'You must specify at least one CSS style' if styles.empty?\n\n        begin\n          synchronize { base.style(styles) }\n        rescue NotImplementedError => e\n          begin\n            evaluate_script(STYLE_SCRIPT, *styles)\n          rescue Capybara::NotSupportedByDriverError\n            raise e\n          end\n        end\n      end\n\n      ##\n      #\n      # @return [String]    The value of the form element\n      #\n      def value\n        synchronize { base.value }\n      end\n\n      ##\n      #\n      # Set the value of the form element to the given value.\n      #\n      # @param [String] value    The new value\n      # @param [Hash] options    Driver specific options for how to set the value. Take default values from {Capybara.configure default_set_options}.\n      #\n      # @return [Capybara::Node::Element]  The element\n      def set(value, **options)\n        if ENV.fetch('CAPYBARA_THOROUGH', nil) && readonly?\n          raise Capybara::ReadOnlyElementError, \"Attempt to set readonly element with value: #{value}\"\n        end\n\n        options = session_options.default_set_options.to_h.merge(options)\n        synchronize { base.set(value, **options) }\n        self\n      end\n\n      ##\n      #\n      # Select this node if it is an option element inside a select tag.\n      #\n      # @!macro action_waiting_behavior\n      #   If the driver dynamic pages (JS) and the element is currently non-interactable, this method will\n      #   continuously retry the action until either the element becomes interactable or the maximum\n      #   wait time expires.\n      #\n      #   @param [false, Numeric] wait\n      #     Maximum time to wait for the action to succeed. Defaults to {Capybara.configure default_max_wait_time}.\n      # @return [Capybara::Node::Element]  The element\n      def select_option(wait: nil)\n        synchronize(wait) { base.select_option }\n        self\n      end\n\n      ##\n      #\n      # Unselect this node if it is an option element inside a multiple select tag.\n      #\n      # @macro action_waiting_behavior\n      # @return [Capybara::Node::Element]  The element\n      def unselect_option(wait: nil)\n        synchronize(wait) { base.unselect_option }\n        self\n      end\n\n      ##\n      #\n      # Click the Element.\n      #\n      # @macro action_waiting_behavior\n      # @!macro click_modifiers\n      #   Both x: and y: must be specified if an offset is wanted, if not specified the click will occur at the middle of the element.\n      #   @overload $0(*modifier_keys, wait: nil, **offset)\n      #     @param *modifier_keys [:alt, :control, :meta, :shift] ([]) Keys to be held down when clicking\n      #     @option options [Integer] x  X coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the\n      #       offset will be from the element center, otherwise it will be from the top left corner of the element\n      #     @option options [Integer] y  Y coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the\n      #       offset will be from the element center, otherwise it will be from the top left corner of the element\n      # @option options [Float] delay  Delay between the mouse down and mouse up events in seconds (0)\n      # @return [Capybara::Node::Element]  The element\n      def click(*keys, **options)\n        perform_click_action(keys, **options) do |k, opts|\n          base.click(k, **opts)\n        end\n      end\n\n      ##\n      #\n      # Right Click the Element.\n      #\n      # @macro action_waiting_behavior\n      # @macro click_modifiers\n      # @option options [Float] delay  Delay between the mouse down and mouse up events in seconds (0)\n      # @return [Capybara::Node::Element]  The element\n      def right_click(*keys, **options)\n        perform_click_action(keys, **options) do |k, opts|\n          base.right_click(k, **opts)\n        end\n      end\n\n      ##\n      #\n      # Double Click the Element.\n      #\n      # @macro action_waiting_behavior\n      # @macro click_modifiers\n      # @return [Capybara::Node::Element]  The element\n      def double_click(*keys, **options)\n        perform_click_action(keys, **options) do |k, opts|\n          base.double_click(k, **opts)\n        end\n      end\n\n      ##\n      #\n      # Send Keystrokes to the Element.\n      #\n      # @overload send_keys(keys, ...)\n      #   @param keys [String, Symbol, Array<String,Symbol>]\n      #\n      # Examples:\n      #\n      #     element.send_keys \"foo\"                     #=> value: 'foo'\n      #     element.send_keys \"tet\", :left, \"s\"         #=> value: 'test'\n      #     element.send_keys [:control, 'a'], :space   #=> value: ' ' - assuming ctrl-a selects all contents\n      #\n      # Symbols supported for keys:\n      # * :cancel\n      # * :help\n      # * :backspace\n      # * :tab\n      # * :clear\n      # * :return\n      # * :enter\n      # * :shift\n      # * :control\n      # * :alt\n      # * :pause\n      # * :escape\n      # * :space\n      # * :page_up\n      # * :page_down\n      # * :end\n      # * :home\n      # * :left\n      # * :up\n      # * :right\n      # * :down\n      # * :insert\n      # * :delete\n      # * :semicolon\n      # * :equals\n      # * :numpad0\n      # * :numpad1\n      # * :numpad2\n      # * :numpad3\n      # * :numpad4\n      # * :numpad5\n      # * :numpad6\n      # * :numpad7\n      # * :numpad8\n      # * :numpad9\n      # * :multiply      - numeric keypad *\n      # * :add           - numeric keypad +\n      # * :separator     - numeric keypad 'separator' key ??\n      # * :subtract      - numeric keypad -\n      # * :decimal       - numeric keypad .\n      # * :divide        - numeric keypad /\n      # * :f1\n      # * :f2\n      # * :f3\n      # * :f4\n      # * :f5\n      # * :f6\n      # * :f7\n      # * :f8\n      # * :f9\n      # * :f10\n      # * :f11\n      # * :f12\n      # * :meta\n      # * :command      - alias of :meta\n      #\n      # @return [Capybara::Node::Element]  The element\n      def send_keys(*args)\n        synchronize { base.send_keys(*args) }\n        self\n      end\n\n      ##\n      #\n      # Hover on the Element.\n      #\n      # @return [Capybara::Node::Element]  The element\n      def hover\n        synchronize { base.hover }\n        self\n      end\n\n      ##\n      #\n      # @return [String]      The tag name of the element\n      #\n      def tag_name\n        # Element type is immutable so cache it\n        @tag_name ||= initial_cache[:tag_name] || synchronize { base.tag_name }\n      end\n\n      ##\n      #\n      # Whether or not the element is visible. Not all drivers support CSS, so\n      # the result may be inaccurate.\n      #\n      # @return [Boolean]     Whether the element is visible\n      #\n      def visible?\n        synchronize { base.visible? }\n      end\n\n      ##\n      #\n      # Whether or not the element is currently in the viewport and it (or descendants)\n      # would be considered clickable at the elements center point.\n      #\n      # @return [Boolean]     Whether the elements center is obscured.\n      #\n      def obscured?\n        synchronize { base.obscured? }\n      end\n\n      ##\n      #\n      # Whether or not the element is checked.\n      #\n      # @return [Boolean]     Whether the element is checked\n      #\n      def checked?\n        synchronize { base.checked? }\n      end\n\n      ##\n      #\n      # Whether or not the element is selected.\n      #\n      # @return [Boolean]     Whether the element is selected\n      #\n      def selected?\n        synchronize { base.selected? }\n      end\n\n      ##\n      #\n      # Whether or not the element is disabled.\n      #\n      # @return [Boolean]     Whether the element is disabled\n      #\n      def disabled?\n        synchronize { base.disabled? }\n      end\n\n      ##\n      #\n      # Whether or not the element is readonly.\n      #\n      # @return [Boolean]     Whether the element is readonly\n      #\n      def readonly?\n        synchronize { base.readonly? }\n      end\n\n      ##\n      #\n      # Whether or not the element supports multiple results.\n      #\n      # @return [Boolean]     Whether the element supports multiple results.\n      #\n      def multiple?\n        synchronize { base.multiple? }\n      end\n\n      ##\n      #\n      # An XPath expression describing where on the page the element can be found.\n      #\n      # @return [String]      An XPath expression\n      #\n      def path\n        synchronize { base.path }\n      end\n\n      def rect\n        synchronize { base.rect }\n      end\n\n      ##\n      #\n      # Trigger any event on the current element, for example mouseover or focus\n      # events. Not supported with the Selenium driver, and SHOULDN'T BE USED IN TESTING unless you\n      # fully understand why you're using it, that it can allow actions a user could never\n      # perform, and that it may completely invalidate your test.\n      #\n      # @param [String] event       The name of the event to trigger\n      #\n      # @return [Capybara::Node::Element]  The element\n      def trigger(event)\n        synchronize { base.trigger(event) }\n        self\n      end\n\n      ##\n      #\n      # Drag the element to the given other element.\n      #\n      #     source = page.find('#foo')\n      #     target = page.find('#bar')\n      #     source.drag_to(target)\n      #\n      # @param [Capybara::Node::Element] node     The element to drag to\n      # @param [Hash] options  Driver specific options for dragging. May not be supported by all drivers.\n      # @option options [Numeric] :delay   (0.05) When using Chrome/Firefox with Selenium and HTML5 dragging this is the number\n      #                                    of seconds between each stage of the drag.\n      # @option options [Boolean] :html5   When using Chrome/Firefox with Selenium enables to force the use of HTML5\n      #                                    (true) or legacy (false) dragging. If not specified the driver will attempt to\n      #                                    detect the correct method to use.\n      # @option options [Array<Symbol>,Symbol] :drop_modifiers   Modifier keys which should be held while the dragged element is dropped.\n      #\n      #\n      # @return [Capybara::Node::Element]  The dragged element\n      def drag_to(node, **options)\n        synchronize { base.drag_to(node.base, **options) }\n        self\n      end\n\n      ##\n      #\n      # Drop items on the current element.\n      #\n      #     target = page.find('#foo')\n      #     target.drop('/some/path/file.csv')\n      #\n      # @overload drop(path, ...)\n      #   @param [String, #to_path] path Location of the file to drop on the element\n      #\n      # @overload drop(strings, ...)\n      #   @param [Hash] strings A hash of type to data to be dropped - `{ \"text/url\" => \"https://www.google.com\" }`\n      #\n      # @return [Capybara::Node::Element]  The element\n      def drop(*args)\n        options = args.map { |arg| arg.respond_to?(:to_path) ? arg.to_path : arg }\n        synchronize { base.drop(*options) }\n        self\n      end\n\n      ##\n      #\n      # Scroll the page or element.\n      #\n      # @overload scroll_to(position, offset: [0,0])\n      #   Scroll the page or element to its top, bottom or middle.\n      #   @param [:top, :bottom, :center, :current] position\n      #   @param [[Integer, Integer]] offset\n      #\n      # @overload scroll_to(element, align: :top)\n      #   Scroll the page or current element until the given element is aligned at the top, bottom, or center of it.\n      #   @param [Capybara::Node::Element] element   The element to be scrolled into view\n      #   @param [:top, :bottom, :center] align Where to align the element being scrolled into view with relation to the current page/element if possible\n      #\n      # @overload scroll_to(x,y)\n      #   @param [Integer] x    Horizontal scroll offset\n      #   @param [Integer] y    Vertical scroll offset\n      #\n      # @return [Capybara::Node::Element]  The element\n      def scroll_to(pos_or_el_or_x, y = nil, align: :top, offset: nil)\n        case pos_or_el_or_x\n        when Symbol\n          synchronize { base.scroll_to(nil, pos_or_el_or_x) } unless pos_or_el_or_x == :current\n        when Capybara::Node::Element\n          synchronize { base.scroll_to(pos_or_el_or_x.base, align) }\n        else\n          synchronize { base.scroll_to(nil, nil, [pos_or_el_or_x, y]) }\n        end\n        synchronize { base.scroll_by(*offset) } unless offset.nil?\n        self\n      end\n\n      ##\n      #\n      # Return the shadow_root for the current element\n      #\n      # @return [Capybara::Node::Element]  The shadow root\n\n      def shadow_root\n        root = synchronize { base.shadow_root }\n        root && Capybara::Node::Element.new(session, root, nil, nil)\n      end\n\n      ##\n      #\n      # Execute the given JS in the context of the element not returning a result. This is useful for scripts that return\n      # complex objects, such as jQuery statements. {#execute_script} should be used over\n      # {#evaluate_script} whenever a result is not expected or needed. `this` in the script will refer to the element this is called on.\n      #\n      # @param [String] script   A string of JavaScript to execute\n      # @param args  Optional arguments that will be passed to the script. Driver support for this is optional and types of objects supported may differ between drivers\n      #\n      def execute_script(script, *args)\n        session.execute_script(<<~JS, self, *args)\n          (function (){\n            #{script}\n          }).apply(arguments[0], Array.prototype.slice.call(arguments,1));\n        JS\n      end\n\n      ##\n      #\n      # Evaluate the given JS in the context of the element and return the result. Be careful when using this with\n      # scripts that return complex objects, such as jQuery statements. {#execute_script} might\n      # be a better alternative. `this` in the script will refer to the element this is called on.\n      #\n      # @param  [String] script   A string of JavaScript to evaluate\n      # @return [Object]          The result of the evaluated JavaScript (may be driver specific)\n      #\n      def evaluate_script(script, *args)\n        session.evaluate_script(<<~JS, self, *args)\n          (function(){\n            return #{script.strip}\n          }).apply(arguments[0], Array.prototype.slice.call(arguments,1));\n        JS\n      end\n\n      ##\n      #\n      # Evaluate the given JavaScript in the context of the element and obtain the result from a\n      # callback function which will be passed as the last argument to the script. `this` in the\n      # script will refer to the element this is called on.\n      #\n      # @param  [String] script   A string of JavaScript to evaluate\n      # @return [Object]          The result of the evaluated JavaScript (may be driver specific)\n      #\n      def evaluate_async_script(script, *args)\n        session.evaluate_async_script(<<~JS, self, *args)\n          (function (){\n            #{script}\n          }).apply(arguments[0], Array.prototype.slice.call(arguments,1));\n        JS\n      end\n\n      ##\n      #\n      # Toggle the elements background color between white and black for a period of time.\n      #\n      # @return [Capybara::Node::Element]  The element\n      def flash\n        execute_script(<<~JS, 100)\n          async function flash(el, delay){\n            var old_bg = el.style.backgroundColor;\n            var colors = [\"black\", \"white\"];\n            for(var i=0; i<20; i++){\n              el.style.backgroundColor = colors[i % colors.length];\n              await new Promise(resolve => setTimeout(resolve, delay));\n            }\n            el.style.backgroundColor = old_bg;\n          }\n          flash(this, arguments[0]);\n        JS\n\n        self\n      end\n\n      # @api private\n      def reload\n        return self unless @allow_reload\n\n        begin\n          reloaded = @query.resolve_for(query_scope ? query_scope.reload : session)[@query_idx.to_i]\n          @base = reloaded.base if reloaded\n        rescue StandardError => e\n          raise e unless catch_error?(e)\n        end\n        self\n      end\n\n      ##\n      #\n      # A human-readable representation of the element.\n      #\n      # @return [String]  A string representation\n      def inspect\n        %(#<Capybara::Node::Element tag=\"#{base.tag_name}\" path=\"#{base.path}\">)\n      rescue NotSupportedByDriverError\n        %(#<Capybara::Node::Element tag=\"#{base.tag_name}\">)\n      rescue *session.driver.invalid_element_errors\n        %(Obsolete #<Capybara::Node::Element>)\n      end\n\n      # @api private\n      def initial_cache\n        base.respond_to?(:initial_cache) ? base.initial_cache : {}\n      end\n\n      STYLE_SCRIPT = <<~JS\n        (function(){\n          var s = window.getComputedStyle(this);\n          var result = {};\n          for (var i = arguments.length; i--; ) {\n            var property_name = arguments[i];\n            result[property_name] = s.getPropertyValue(property_name);\n          }\n          return result;\n        }).apply(this, arguments)\n      JS\n\n    private\n\n      def perform_click_action(keys, wait: nil, **options)\n        raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ options[:x] ^ options[:y]\n\n        options[:offset] ||= :center if session_options.w3c_click_offset\n        synchronize(wait) { yield keys, options }\n        self\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/finders.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    module Finders\n      ##\n      #\n      # Find an {Capybara::Node::Element} based on the given arguments. {#find} will raise an error if the element\n      # is not found.\n      #\n      #     page.find('#foo').find('.bar')\n      #     page.find(:xpath, './/div[contains(., \"bar\")]')\n      #     page.find('li', text: 'Quox').click_link('Delete')\n      #\n      # @param (see #all)\n      #\n      # @macro waiting_behavior\n      #\n      # @!macro system_filters\n      #   @option options [String, Regexp] text      Only find elements which contain this text or match this regexp\n      #   @option options [String, Regexp, String] exact_text\n      #     When String the elements contained text must match exactly, when Boolean controls whether the `text` option must match exactly.\n      #     Defaults to {Capybara.configure exact_text}.\n      #   @option options [Boolean] normalize_ws\n      #     Whether the `text`/`exact_text` options are compared against element text with whitespace normalized or as returned by the driver.\n      #     Defaults to {Capybara.configure default_normalize_ws}.\n      #   @option options [Boolean, Symbol] visible\n      #     Only find elements with the specified visibility. Defaults to behavior indicated by {Capybara.configure ignore_hidden_elements}.\n      #       * true - only finds visible elements.\n      #       * false - finds invisible _and_ visible elements.\n      #       * :all - same as false; finds visible and invisible elements.\n      #       * :hidden - only finds invisible elements.\n      #       * :visible - same as true; only finds visible elements.\n      #   @option options [Boolean] obscured  Only find elements with the specified obscured state:\n      #                                       * true - only find elements whose centerpoint is not in the viewport or is obscured by another non-descendant element.\n      #                                       * false - only find elements whose centerpoint is in the viewport and is not obscured by other non-descendant elements.\n      #   @option options [String, Regexp]  id           Only find elements with an id that matches the value passed\n      #   @option options [String, Array<String>, Regexp] class  Only find elements with matching class/classes.\n      #                                            * Absence of a class can be checked by prefixing the class name with `!`\n      #                                            * If you need to check for existence of a class name that starts with `!` then prefix with `!!`\n      #\n      #                                                class:['a', '!b', '!!!c'] # limit to elements with class 'a' and '!c' but not class 'b'\n      #\n      #   @option options [String, Regexp, Hash] style  Only find elements with matching style. String and Regexp will be checked against text of the elements `style` attribute, while a Hash will be compared against the elements full style\n      #   @option options [Boolean] exact            Control whether `is` expressions in the given XPath match exactly or partially. Defaults to {Capybara.configure exact}.\n      #   @option options [Symbol] match        The matching strategy to use. Defaults to {Capybara.configure match}.\n      #\n      # @return [Capybara::Node::Element]      The found element\n      # @raise  [Capybara::ElementNotFound]    If the element can't be found before time expires\n      #\n      def find(*args, **options, &optional_filter_block)\n        options[:session_options] = session_options\n        count_options = options.slice(*Capybara::Queries::BaseQuery::COUNT_KEYS)\n        unless count_options.empty?\n          Capybara::Helpers.warn(\n            \"'find' does not support count options (#{count_options}) ignoring. \" \\\n            \"Called from: #{Capybara::Helpers.filter_backtrace(caller)}\"\n          )\n        end\n        synced_resolve Capybara::Queries::SelectorQuery.new(*args, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find an {Capybara::Node::Element} based on the given arguments that is also an ancestor of the element called on.\n      # {#ancestor} will raise an error if the element is not found.\n      #\n      # {#ancestor} takes the same options as {#find}.\n      #\n      #     element.ancestor('#foo').find('.bar')\n      #     element.ancestor(:xpath, './/div[contains(., \"bar\")]')\n      #     element.ancestor('ul', text: 'Quox').click_link('Delete')\n      #\n      # @param (see #find)\n      #\n      # @macro waiting_behavior\n      #\n      # @return [Capybara::Node::Element]      The found element\n      # @raise  [Capybara::ElementNotFound]    If the element can't be found before time expires\n      #\n      def ancestor(*args, **options, &optional_filter_block)\n        options[:session_options] = session_options\n        synced_resolve Capybara::Queries::AncestorQuery.new(*args, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find an {Capybara::Node::Element} based on the given arguments that is also a sibling of the element called on.\n      # {#sibling} will raise an error if the element is not found.\n      #\n      # {#sibling} takes the same options as {#find}.\n      #\n      #     element.sibling('#foo').find('.bar')\n      #     element.sibling(:xpath, './/div[contains(., \"bar\")]')\n      #     element.sibling('ul', text: 'Quox').click_link('Delete')\n      #\n      # @param (see #find)\n      #\n      # @macro waiting_behavior\n      #\n      # @return [Capybara::Node::Element]      The found element\n      # @raise  [Capybara::ElementNotFound]    If the element can't be found before time expires\n      #\n      def sibling(*args, **options, &optional_filter_block)\n        options[:session_options] = session_options\n        synced_resolve Capybara::Queries::SiblingQuery.new(*args, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find a form field on the page. The field can be found by its name, id or label text.\n      #\n      # @overload find_field([locator], **options)\n      #   @param [String] locator             name, id, {Capybara.configure test_id} attribute, placeholder or text of associated label element\n      #\n      #   @macro waiting_behavior\n      #\n      #\n      #   @option options [Boolean] checked       Match checked field?\n      #   @option options [Boolean] unchecked     Match unchecked field?\n      #   @option options [Boolean, Symbol] disabled (false)  Match disabled field?\n      #                                                       * true - only finds a disabled field\n      #                                                       * false - only finds an enabled field\n      #                                                       * :all - finds either an enabled or disabled field\n      #   @option options [Boolean] readonly      Match readonly field?\n      #   @option options [String, Regexp] with   Value of field to match on\n      #   @option options [String] type           Type of field to match on\n      #   @option options [Boolean] multiple      Match fields that can have multiple values?\n      #   @option options [String, Regexp] id     Match fields that match the id attribute\n      #   @option options [String] name           Match fields that match the name attribute\n      #   @option options [String] placeholder    Match fields that match the placeholder attribute\n      #   @option options [String, Array<String>, Regexp] class Match fields that match the class(es) passed\n      # @return [Capybara::Node::Element]   The found element\n      #\n      def find_field(locator = nil, **options, &optional_filter_block)\n        find(:field, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find a link on the page. The link can be found by its id or text.\n      #\n      # @overload find_link([locator], **options)\n      #   @param [String] locator            id, {Capybara.configure test_id} attribute, title, text, or alt of enclosed img element\n      #\n      #   @macro waiting_behavior\n      #\n      #   @option options [String,Regexp,nil] href    Value to match against the links href, if `nil` finds link placeholders (`<a>` elements with no href attribute), if `false` ignores the href\n      #   @option options [String, Regexp] id         Match links with the id provided\n      #   @option options [String] title              Match links with the title provided\n      #   @option options [String] alt                Match links with a contained img element whose alt matches\n      #   @option options [String, Boolean] download  Match links with the download provided\n      #   @option options [String] target             Match links with the target provided\n      #   @option options [String, Array<String>, Regexp] class    Match links that match the class(es) provided\n      # @return [Capybara::Node::Element]   The found element\n      #\n      def find_link(locator = nil, **options, &optional_filter_block)\n        find(:link, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find a button on the page.\n      # This can be any `<input>` element of type submit, reset, image, button or it can be a\n      # `<button>` element. All buttons can be found by their id, name, {Capybara.configure test_id} attribute, value, or title.\n      # `<button>` elements can also be found by their text content, and image `<input>` elements by their alt attribute.\n      #\n      # @overload find_button([locator], **options)\n      #   @param [String] locator            id, name, {Capybara.configure test_id} attribute, value, title, text content, alt of image\n      #\n      #   @macro waiting_behavior\n      #\n      #   @option options [Boolean, Symbol] disabled (false)  Match disabled button?\n      #                                                       * true - only finds a disabled button\n      #                                                       * false - only finds an enabled button\n      #                                                       * :all - finds either an enabled or disabled button\n      #   @option options [String, Regexp] id                 Match buttons with the id provided\n      #   @option options [String] name                       Match buttons with the name provided\n      #   @option options [String] title                      Match buttons with the title provided\n      #   @option options [String] value                      Match buttons with the value provided\n      #   @option options [String, Array<String>, Regexp] class    Match buttons that match the class(es) provided\n      # @return [Capybara::Node::Element]   The found element\n      #\n      def find_button(locator = nil, **options, &optional_filter_block)\n        find(:button, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Find a element on the page, given its id.\n      #\n      # @macro waiting_behavior\n      #\n      # @param [String] id                  id of element\n      #\n      # @return [Capybara::Node::Element]   The found element\n      #\n      def find_by_id(id, **options, &optional_filter_block)\n        find(:id, id, **options, &optional_filter_block)\n      end\n\n      ##\n      # @!method all([kind = Capybara.default_selector], locator = nil, **options)\n      #\n      # Find all elements on the page matching the given selector\n      # and options.\n      #\n      # Both XPath and CSS expressions are supported, but Capybara\n      # does not try to automatically distinguish between them. The\n      # following statements are equivalent:\n      #\n      #     page.all(:css, 'a#person_123')\n      #     page.all(:xpath, './/a[@id=\"person_123\"]')\n      #\n      # If the type of selector is left out, Capybara uses\n      # {Capybara.configure default_selector}. It's set to `:css` by default.\n      #\n      #     page.all(\"a#person_123\")\n      #\n      #     Capybara.default_selector = :xpath\n      #     page.all('.//a[@id=\"person_123\"]')\n      #\n      # The set of found elements can further be restricted by specifying\n      # options. It's possible to select elements by their text or visibility:\n      #\n      #     page.all('a', text: 'Home')\n      #     page.all('#menu li', visible: true)\n      #\n      # By default Capybara's waiting behavior will wait up to {Capybara.configure default_max_wait_time}\n      # seconds for matching elements to be available and then return an empty result if none\n      # are available. It is possible to set expectations on the number of results located and\n      # Capybara will raise an exception if the number of elements located don't satisfy the\n      # specified conditions. The expectations can be set using:\n      #\n      #     page.assert_selector('p#foo', count: 4)\n      #     page.assert_selector('p#foo', maximum: 10)\n      #     page.assert_selector('p#foo', minimum: 1)\n      #     page.assert_selector('p#foo', between: 1..10)\n      #\n      # @param [Symbol] kind                       Optional selector type (:css, :xpath, :field, etc.). Defaults to {Capybara.configure default_selector}.\n      # @param [String] locator                    The locator for the specified selector\n      # @macro system_filters\n      # @macro waiting_behavior\n      # @option options [Integer] count            Exact number of matches that are expected to be found\n      # @option options [Integer] maximum          Maximum number of matches that are expected to be found\n      # @option options [Integer] minimum          Minimum number of matches that are expected to be found\n      # @option options [Range]   between          Number of matches found must be within the given range\n      # @option options [Boolean] allow_reload     Beta feature - May be removed in any version.\n      #   When `true` allows elements to be reloaded if they become stale. This is an advanced behavior and should only be used\n      #   if you fully understand the potential ramifications. The results can be confusing on dynamic pages. Defaults to `false`\n      # @overload all([kind = Capybara.default_selector], locator = nil, **options)\n      # @overload all([kind = Capybara.default_selector], locator = nil, **options, &filter_block)\n      #   @yieldparam element [Capybara::Node::Element]  The element being considered for inclusion in the results\n      #   @yieldreturn [Boolean]                     Should the element be considered in the results?\n      # @return [Capybara::Result]                   A collection of found elements\n      # @raise [Capybara::ExpectationNotMet]         The number of elements found doesn't match the specified conditions\n      def all(*args, allow_reload: false, **options, &optional_filter_block)\n        minimum_specified = options_include_minimum?(options)\n        options = { minimum: 1 }.merge(options) unless minimum_specified\n        options[:session_options] = session_options\n        query = Capybara::Queries::SelectorQuery.new(*args, **options, &optional_filter_block)\n        result = nil\n        begin\n          synchronize(query.wait) do\n            result = query.resolve_for(self)\n            result.allow_reload! if allow_reload\n            raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?\n\n            result\n          end\n        rescue Capybara::ExpectationNotMet\n          raise if minimum_specified || (result.compare_count == 1)\n\n          Result.new([], nil)\n        end\n      end\n      alias_method :find_all, :all\n\n      ##\n      #\n      # Find the first element on the page matching the given selector\n      # and options. By default {#first} will wait up to {Capybara.configure default_max_wait_time}\n      # seconds for matching elements to appear and then raise an error if no matching\n      # element is found, or `nil` if the provided count options allow for empty results.\n      #\n      # @overload first([kind], locator, options)\n      #   @param [Symbol] kind                       The type of selector\n      #   @param [String] locator                    The selector\n      #   @param [Hash] options                      Additional options; see {#all}\n      # @return [Capybara::Node::Element]            The found element or nil\n      # @raise  [Capybara::ElementNotFound]          If element(s) matching the provided options can't be found before time expires\n      #\n      def first(*args, **options, &optional_filter_block)\n        options = { minimum: 1 }.merge(options) unless options_include_minimum?(options)\n        all(*args, **options, &optional_filter_block).first\n      end\n\n    private\n\n      def synced_resolve(query)\n        synchronize(query.wait) do\n          if prefer_exact?(query)\n            result = query.resolve_for(self, true)\n            result = query.resolve_for(self, false) if result.empty? && query.supports_exact? && !query.exact?\n          else\n            result = query.resolve_for(self)\n          end\n\n          if ambiguous?(query, result)\n            raise Capybara::Ambiguous, \"Ambiguous match, found #{result.size} elements matching #{query.applied_description}\"\n          end\n          raise Capybara::ElementNotFound, \"Unable to find #{query.applied_description}\" if result.empty?\n\n          result.first\n        end.tap(&:allow_reload!)\n      end\n\n      def ambiguous?(query, result)\n        %i[one smart].include?(query.match) && (result.size > 1)\n      end\n\n      def prefer_exact?(query)\n        %i[smart prefer_exact].include?(query.match)\n      end\n\n      def options_include_minimum?(opts)\n        %i[count minimum between].any? { |key| opts.key?(key) }\n      end\n\n      def parent\n        first(:xpath, './parent::*', minimum: 0)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/matchers.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    module Matchers\n      ##\n      #\n      # Checks if a given selector is on the page or a descendant of the current node.\n      #\n      #     page.has_selector?('p#foo')\n      #     page.has_selector?(:xpath, './/p[@id=\"foo\"]')\n      #     page.has_selector?(:foo)\n      #\n      # By default it will check if the expression occurs at least once,\n      # but a different number can be specified.\n      #\n      #     page.has_selector?('p.foo', count: 4)\n      #\n      # This will check if the expression occurs exactly 4 times.\n      #\n      # It also accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      #     page.has_selector?('li', text: 'Horse', visible: true)\n      #\n      # {#has_selector?} can also accept XPath expressions generated by the\n      # XPath gem:\n      #\n      #     page.has_selector?(:xpath, XPath.descendant(:p))\n      #\n      # @param (see Capybara::Node::Finders#all)\n      # @option options [Integer] :count (nil)     Number of matching elements that should exist\n      # @option options [Integer] :minimum (nil)   Minimum number of matching elements that should exist\n      # @option options [Integer] :maximum (nil)   Maximum number of matching elements that should exist\n      # @option options [Range]   :between (nil)   Range of number of matching elements that should exist\n      # @return [Boolean]                       If the expression exists\n      #\n      def has_selector?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_selector(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Checks if a given selector is not on the page or a descendant of the current node.\n      # Usage is identical to {#has_selector?}.\n      #\n      # @param (see #has_selector?)\n      # @return [Boolean]\n      #\n      def has_no_selector?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_no_selector(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Checks if a an element has the specified CSS styles.\n      #\n      #     element.matches_style?( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )\n      #\n      # @param styles [Hash]\n      # @return [Boolean]                       If the styles match\n      #\n      def matches_style?(styles = nil, **options)\n        styles, options = options, {} if styles.nil?\n        make_predicate(options) { assert_matches_style(styles, **options) }\n      end\n\n      ##\n      # @deprecated Use {#matches_style?} instead.\n      #\n      def has_style?(styles = nil, **options)\n        Capybara::Helpers.warn \"DEPRECATED: has_style? is deprecated, please use matches_style? : #{Capybara::Helpers.filter_backtrace(caller)}\"\n        matches_style?(styles, **options)\n      end\n\n      ##\n      #\n      # Asserts that a given selector is on the page or a descendant of the current node.\n      #\n      #     page.assert_selector('p#foo')\n      #     page.assert_selector(:xpath, './/p[@id=\"foo\"]')\n      #     page.assert_selector(:foo)\n      #\n      # By default it will check if the expression occurs at least once,\n      # but a different number can be specified.\n      #\n      #     page.assert_selector('p#foo', count: 4)\n      #\n      # This will check if the expression occurs exactly 4 times. See\n      # {Capybara::Node::Finders#all} for other available result size options.\n      #\n      # If a `:count` of 0 is specified, it will behave like {#assert_no_selector};\n      # however, use of that method is preferred over this one.\n      #\n      # It also accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      #     page.assert_selector('li', text: 'Horse', visible: true)\n      #\n      # {#assert_selector} can also accept XPath expressions generated by the\n      # XPath gem:\n      #\n      #     page.assert_selector(:xpath, XPath.descendant(:p))\n      #\n      # @param (see Capybara::Node::Finders#all)\n      # @option options [Integer] :count (nil)    Number of times the expression should occur\n      # @raise [Capybara::ExpectationNotMet]      If the selector does not exist\n      #\n      def assert_selector(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block) do |result, query|\n          unless result.matches_count? && (result.any? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.failure_message\n          end\n        end\n      end\n\n      ##\n      #\n      # Asserts that an element has the specified CSS styles.\n      #\n      #     element.assert_matches_style( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )\n      #\n      # @param styles [Hash]\n      # @raise [Capybara::ExpectationNotMet]    If the element doesn't have the specified styles\n      #\n      def assert_matches_style(styles = nil, **options)\n        styles, options = options, {} if styles.nil?\n        query_args, query_opts = _set_query_session_options(styles, options)\n        query = Capybara::Queries::StyleQuery.new(*query_args, **query_opts)\n        synchronize(query.wait) do\n          raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)\n        end\n        true\n      end\n\n      ##\n      # @deprecated Use {#assert_matches_style} instead.\n      #\n      def assert_style(styles = nil, **options)\n        warn 'assert_style is deprecated, please use assert_matches_style instead'\n        assert_matches_style(styles, **options)\n      end\n\n      # Asserts that all of the provided selectors are present on the given page\n      # or descendants of the current node.  If options are provided, the assertion\n      # will check that each locator is present with those options as well (other than `:wait`).\n      #\n      #     page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)\n      #     page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')\n      #\n      # It accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      # The `:wait` option applies to all of the selectors as a group, so all of the locators must be present\n      # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.\n      #\n      # @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, **options)\n      #\n      def assert_all_of_selectors(*args, **options, &optional_filter_block)\n        _verify_multiple(*args, **options) do |selector, locator, opts|\n          assert_selector(selector, locator, opts, &optional_filter_block)\n        end\n      end\n\n      # Asserts that none of the provided selectors are present on the given page\n      # or descendants of the current node. If options are provided, the assertion\n      # will check that each locator is not present with those options as well (other than `:wait`).\n      #\n      #     page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)\n      #     page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')\n      #\n      # It accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      # The `:wait` option applies to all of the selectors as a group, so none of the locators must be present\n      # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.\n      #\n      # @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, **options)\n      #\n      def assert_none_of_selectors(*args, **options, &optional_filter_block)\n        _verify_multiple(*args, **options) do |selector, locator, opts|\n          assert_no_selector(selector, locator, opts, &optional_filter_block)\n        end\n      end\n\n      # Asserts that any of the provided selectors are present on the given page\n      # or descendants of the current node. If options are provided, the assertion\n      # will check that each locator is present with those options as well (other than `:wait`).\n      #\n      #     page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)\n      #     page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')\n      #\n      # It accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      # The `:wait` option applies to all of the selectors as a group, so any of the locators must be present\n      # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.\n      #\n      # @overload assert_any_of_selectors([kind = Capybara.default_selector], *locators, **options)\n      #\n      def assert_any_of_selectors(*args, wait: nil, **options, &optional_filter_block)\n        wait = session_options.default_max_wait_time if wait.nil?\n        selector = extract_selector(args)\n        synchronize(wait) do\n          res = args.map do |locator|\n            assert_selector(selector, locator, options, &optional_filter_block)\n            break nil\n          rescue Capybara::ExpectationNotMet => e\n            e.message\n          end\n          raise Capybara::ExpectationNotMet, res.join(' or ') if res\n\n          true\n        end\n      end\n\n      ##\n      #\n      # Asserts that a given selector is not on the page or a descendant of the current node.\n      # Usage is identical to {#assert_selector}.\n      #\n      # Query options such as `:count`, `:minimum`, `:maximum`, and `:between` are\n      # considered to be an integral part of the selector. This will return\n      # `true`, for example, if a page contains 4 anchors but the query expects 5:\n      #\n      #     page.assert_no_selector('a', minimum: 1) # Found, raises Capybara::ExpectationNotMet\n      #     page.assert_no_selector('a', count: 4)   # Found, raises Capybara::ExpectationNotMet\n      #     page.assert_no_selector('a', count: 5)   # Not Found, returns true\n      #\n      # @param (see #assert_selector)\n      # @raise [Capybara::ExpectationNotMet]      If the selector exists\n      #\n      def assert_no_selector(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block) do |result, query|\n          if result.matches_count? && (!result.empty? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.negative_failure_message\n          end\n        end\n      end\n\n      ##\n      #\n      # Checks if a given XPath expression is on the page or a descendant of the current node.\n      #\n      #     page.has_xpath?('.//p[@id=\"foo\"]')\n      #\n      # By default it will check if the expression occurs at least once,\n      # but a different number can be specified.\n      #\n      #     page.has_xpath?('.//p[@id=\"foo\"]', count: 4)\n      #\n      # This will check if the expression occurs exactly 4 times.\n      #\n      # It also accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      #     page.has_xpath?('.//li', text: 'Horse', visible: true)\n      #\n      # {#has_xpath?} can also accept XPath expressions generated by the\n      # XPath gem:\n      #\n      #     xpath = XPath.generate { |x| x.descendant(:p) }\n      #     page.has_xpath?(xpath)\n      #\n      # @param [String] path                      An XPath expression\n      # @param options                            (see Capybara::Node::Finders#all)\n      # @option options [Integer] :count (nil)    Number of times the expression should occur\n      # @return [Boolean]                         If the expression exists\n      #\n      def has_xpath?(path, **options, &optional_filter_block)\n        has_selector?(:xpath, path, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if a given XPath expression is not on the page or a descendant of the current node.\n      # Usage is identical to {#has_xpath?}.\n      #\n      # @param (see #has_xpath?)\n      # @return [Boolean]\n      #\n      def has_no_xpath?(path, **options, &optional_filter_block)\n        has_no_selector?(:xpath, path, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if a given CSS selector is on the page or a descendant of the current node.\n      #\n      #     page.has_css?('p#foo')\n      #\n      # By default it will check if the selector occurs at least once,\n      # but a different number can be specified.\n      #\n      #     page.has_css?('p#foo', count: 4)\n      #\n      # This will check if the selector occurs exactly 4 times.\n      #\n      # It also accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      #     page.has_css?('li', text: 'Horse', visible: true)\n      #\n      # @param [String] path                      A CSS selector\n      # @param options                            (see Capybara::Node::Finders#all)\n      # @option options [Integer] :count (nil)    Number of times the selector should occur\n      # @return [Boolean]                         If the selector exists\n      #\n      def has_css?(path, **options, &optional_filter_block)\n        has_selector?(:css, path, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if a given CSS selector is not on the page or a descendant of the current node.\n      # Usage is identical to {#has_css?}.\n      #\n      # @param (see #has_css?)\n      # @return [Boolean]\n      #\n      def has_no_css?(path, **options, &optional_filter_block)\n        has_no_selector?(:css, path, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a element with the given\n      # local name.\n      #\n      # @param [String] locator           The local name of a element to check for\n      # @option options [String, Regexp]  The attributes values of matching elements\n      # @return [Boolean]                 Whether it exists\n      #\n      def has_element?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:element, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no element with the given\n      # local name.\n      #\n      # @param (see #has_element?)\n      # @return [Boolean]            Whether it doesn't exist\n      #\n      def has_no_element?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:element, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a link with the given\n      # text or id.\n      #\n      # @param [String] locator           The text or id of a link to check for\n      # @option options [String, Regexp] :href    The value the href attribute must be\n      # @return [Boolean]                 Whether it exists\n      #\n      def has_link?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:link, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no link with the given\n      # text or id.\n      #\n      # @param (see #has_link?)\n      # @return [Boolean]            Whether it doesn't exist\n      #\n      def has_no_link?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:link, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a button with the given\n      # text, value or id.\n      #\n      # @param [String] locator      The text, value or id of a button to check for\n      # @return [Boolean]            Whether it exists\n      #\n      def has_button?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:button, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no button with the given\n      # text, value or id.\n      #\n      # @param [String] locator      The text, value or id of a button to check for\n      # @return [Boolean]            Whether it doesn't exist\n      #\n      def has_no_button?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:button, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a form field with the given\n      # label, name or id.\n      #\n      # For text fields and other textual fields, such as textareas and\n      # HTML5 email/url/etc. fields, it's possible to specify a `:with`\n      # option to specify the text the field should contain:\n      #\n      #     page.has_field?('Name', with: 'Jonas')\n      #\n      # It is also possible to filter by the field type attribute:\n      #\n      #     page.has_field?('Email', type: 'email')\n      #\n      # NOTE: 'textarea' and 'select' are valid type values, matching the associated tag names.\n      #\n      # @param [String] locator                  The label, name or id of a field to check for\n      # @option options [String, Regexp] :with   The text content of the field or a Regexp to match\n      # @option options [String] :type           The type attribute of the field\n      # @return [Boolean]                        Whether it exists\n      #\n      def has_field?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:field, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no form field with the given\n      # label, name or id. See {#has_field?}.\n      #\n      # @param [String] locator                  The label, name or id of a field to check for\n      # @option options [String, Regexp] :with   The text content of the field or a Regexp to match\n      # @option options [String] :type           The type attribute of the field\n      # @return [Boolean]                        Whether it doesn't exist\n      #\n      def has_no_field?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:field, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a radio button or\n      # checkbox with the given label, value, id, or {Capybara.configure test_id} attribute that is currently\n      # checked.\n      #\n      # @param [String] locator           The label, name or id of a checked field\n      # @return [Boolean]                 Whether it exists\n      #\n      def has_checked_field?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:field, locator, **options.merge(checked: true), &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no radio button or\n      # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently\n      # checked.\n      #\n      # @param [String] locator           The label, name or id of a checked field\n      # @return [Boolean]                 Whether it doesn't exist\n      #\n      def has_no_checked_field?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:field, locator, **options.merge(checked: true), &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a radio button or\n      # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently\n      # unchecked.\n      #\n      # @param [String] locator           The label, name or id of an unchecked field\n      # @return [Boolean]                 Whether it exists\n      #\n      def has_unchecked_field?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:field, locator, **options.merge(unchecked: true), &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no radio button or\n      # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently\n      # unchecked.\n      #\n      # @param [String] locator           The label, name or id of an unchecked field\n      # @return [Boolean]                 Whether it doesn't exist\n      #\n      def has_no_unchecked_field?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:field, locator, **options.merge(unchecked: true), &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a select field with the\n      # given label, name or id.\n      #\n      # It can be specified which option should currently be selected:\n      #\n      #     page.has_select?('Language', selected: 'German')\n      #\n      # For multiple select boxes, several options may be specified:\n      #\n      #     page.has_select?('Language', selected: ['English', 'German'])\n      #\n      # It's also possible to check if the exact set of options exists for\n      # this select box:\n      #\n      #     page.has_select?('Language', options: ['English', 'German', 'Spanish'])\n      #\n      # You can also check for a partial set of options:\n      #\n      #     page.has_select?('Language', with_options: ['English', 'German'])\n      #\n      # @param [String] locator                         The label, name or id of a select box\n      # @option options [Array] :options                Options which should be contained in this select box\n      # @option options [Array] :with_options           Partial set of options which should be contained in this select box\n      # @option options [String, Array] :selected       Options which should be selected\n      # @option options [String, Array] :with_selected  Partial set of options which should minimally be selected\n      # @return [Boolean]                               Whether it exists\n      #\n      def has_select?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:select, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no select field with the\n      # given label, name or id. See {#has_select?}.\n      #\n      # @param (see #has_select?)\n      # @return [Boolean]     Whether it doesn't exist\n      #\n      def has_no_select?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:select, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has a table with the given id\n      # or caption:\n      #\n      #    page.has_table?('People')\n      #\n      # @param [String] locator  The id or caption of a table\n      # @option options [Array<Array<String>>] :rows\n      #   Text which should be contained in the tables `<td>` elements organized by row (`<td>` visibility is not considered)\n      # @option options [Array<Array<String>>, Array<Hash<String,String>>] :with_rows\n      #   Partial set of text which should be contained in the tables `<td>` elements organized by row (`<td>` visibility is not considered)\n      # @option options [Array<Array<String>>] :cols\n      #   Text which should be contained in the tables `<td>` elements organized by column (`<td>` visibility is not considered)\n      # @option options [Array<Array<String>>, Array<Hash<String,String>>] :with_cols\n      #   Partial set of text which should be contained in the tables `<td>` elements organized by column (`<td>` visibility is not considered)\n      # @return [Boolean]        Whether it exists\n      #\n      def has_table?(locator = nil, **options, &optional_filter_block)\n        has_selector?(:table, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the page or current node has no table with the given id\n      # or caption. See {#has_table?}.\n      #\n      # @param (see #has_table?)\n      # @return [Boolean]       Whether it doesn't exist\n      #\n      def has_no_table?(locator = nil, **options, &optional_filter_block)\n        has_no_selector?(:table, locator, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Asserts that the current node matches a given selector.\n      #\n      #     node.assert_matches_selector('p#foo')\n      #     node.assert_matches_selector(:xpath, '//p[@id=\"foo\"]')\n      #     node.assert_matches_selector(:foo)\n      #\n      # It also accepts all options that {Capybara::Node::Finders#all} accepts,\n      # such as `:text` and `:visible`.\n      #\n      #     node.assert_matches_selector('li', text: 'Horse', visible: true)\n      #\n      # @param (see Capybara::Node::Finders#all)\n      # @raise [Capybara::ExpectationNotMet]      If the selector does not match\n      #\n      def assert_matches_selector(*args, &optional_filter_block)\n        _verify_match_result(args, optional_filter_block) do |result|\n          raise Capybara::ExpectationNotMet, 'Item does not match the provided selector' unless result.include? self\n        end\n      end\n\n      ##\n      #\n      # Asserts that the current node does not match a given selector.\n      # Usage is identical to {#assert_matches_selector}.\n      #\n      # @param (see #assert_matches_selector)\n      # @raise [Capybara::ExpectationNotMet]      If the selector matches\n      #\n      def assert_not_matches_selector(*args, &optional_filter_block)\n        _verify_match_result(args, optional_filter_block) do |result|\n          raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self\n        end\n      end\n\n      ##\n      #\n      # Checks if the current node matches given selector.\n      #\n      # @param (see #has_selector?)\n      # @return [Boolean]\n      #\n      def matches_selector?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_matches_selector(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Checks if the current node matches given XPath expression.\n      #\n      # @param [String, XPath::Expression] xpath The XPath expression to match against the current code\n      # @return [Boolean]\n      #\n      def matches_xpath?(xpath, **options, &optional_filter_block)\n        matches_selector?(:xpath, xpath, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the current node matches given CSS selector.\n      #\n      # @param [String] css The CSS selector to match against the current code\n      # @return [Boolean]\n      #\n      def matches_css?(css, **options, &optional_filter_block)\n        matches_selector?(:css, css, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the current node does not match given selector.\n      # Usage is identical to {#has_selector?}.\n      #\n      # @param (see #has_selector?)\n      # @return [Boolean]\n      #\n      def not_matches_selector?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_not_matches_selector(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Checks if the current node does not match given XPath expression.\n      #\n      # @param [String, XPath::Expression] xpath The XPath expression to match against the current code\n      # @return [Boolean]\n      #\n      def not_matches_xpath?(xpath, **options, &optional_filter_block)\n        not_matches_selector?(:xpath, xpath, **options, &optional_filter_block)\n      end\n\n      ##\n      #\n      # Checks if the current node does not match given CSS selector.\n      #\n      # @param [String] css The CSS selector to match against the current code\n      # @return [Boolean]\n      #\n      def not_matches_css?(css, **options, &optional_filter_block)\n        not_matches_selector?(:css, css, **options, &optional_filter_block)\n      end\n\n      ##\n      # Asserts that the page or current node has the given text content,\n      # ignoring any HTML tags.\n      #\n      # @!macro text_query_params\n      #   @overload $0(type, text, **options)\n      #     @param [:all, :visible] type               Whether to check for only visible or all text. If this parameter is missing or nil then we use the value of {Capybara.configure ignore_hidden_elements}, which defaults to `true`, corresponding to `:visible`.\n      #     @param [String, Regexp] text               The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.\n      #     @option options [Integer] :count (nil)     Number of times the text is expected to occur\n      #     @option options [Integer] :minimum (nil)   Minimum number of times the text is expected to occur\n      #     @option options [Integer] :maximum (nil)   Maximum number of times the text is expected to occur\n      #     @option options [Range]   :between (nil)   Range of times that is expected to contain number of times text occurs\n      #     @option options [Numeric] :wait            Maximum time that Capybara will wait for text to eq/match given string/regexp argument. Defaults to {Capybara.configure default_max_wait_time}.\n      #     @option options [Boolean] :exact           Whether text must be an exact match or just substring. Defaults to {Capybara.configure exact_text}.\n      #     @option options [Boolean] :normalize_ws (false) When `true` replace all whitespace with standard spaces and collapse consecutive whitespace to a single space\n      #   @overload $0(text, **options)\n      #     @param [String, Regexp] text               The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.\n      #     @option options [Integer] :count (nil)     Number of times the text is expected to occur\n      #     @option options [Integer] :minimum (nil)   Minimum number of times the text is expected to occur\n      #     @option options [Integer] :maximum (nil)   Maximum number of times the text is expected to occur\n      #     @option options [Range]   :between (nil)   Range of times that is expected to contain number of times text occurs\n      #     @option options [Numeric] :wait            Maximum time that Capybara will wait for text to eq/match given string/regexp argument. Defaults to {Capybara.configure default_max_wait_time}.\n      #     @option options [Boolean] :exact           Whether text must be an exact match or just substring. Defaults to {Capybara.configure exact_text}.\n      #     @option options [Boolean] :normalize_ws (false) When `true` replace all whitespace with standard spaces and collapse consecutive whitespace to a single space\n      # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n      # @return [true]\n      #\n      def assert_text(type_or_text, *args, **opts)\n        _verify_text(type_or_text, *args, **opts) do |count, query|\n          unless query.matches_count?(count) && (count.positive? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, query.failure_message\n          end\n        end\n      end\n\n      ##\n      # Asserts that the page or current node doesn't have the given text content,\n      # ignoring any HTML tags.\n      #\n      # @macro text_query_params\n      # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n      # @return [true]\n      #\n      def assert_no_text(type_or_text, *args, **opts)\n        _verify_text(type_or_text, *args, **opts) do |count, query|\n          if query.matches_count?(count) && (count.positive? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, query.negative_failure_message\n          end\n        end\n      end\n\n      ##\n      # Checks if the page or current node has the given text content,\n      # ignoring any HTML tags.\n      #\n      # By default it will check if the text occurs at least once,\n      # but a different number can be specified.\n      #\n      #     page.has_text?('lorem ipsum', between: 2..4)\n      #\n      # This will check if the text occurs from 2 to 4 times.\n      #\n      # @macro text_query_params\n      # @return [Boolean]                            Whether it exists\n      #\n      def has_text?(*args, **options)\n        make_predicate(options) { assert_text(*args, **options) }\n      end\n      alias_method :has_content?, :has_text?\n\n      ##\n      # Checks if the page or current node does not have the given text\n      # content, ignoring any HTML tags and normalizing whitespace.\n      #\n      # @macro text_query_params\n      # @return [Boolean]  Whether it doesn't exist\n      #\n      def has_no_text?(*args, **options)\n        make_predicate(options) { assert_no_text(*args, **options) }\n      end\n      alias_method :has_no_content?, :has_no_text?\n\n      ##\n      #\n      # Asserts that a given selector matches an ancestor of the current node.\n      #\n      #     element.assert_ancestor('p#foo')\n      #\n      # Accepts the same options as {#assert_selector}\n      #\n      # @param (see Capybara::Node::Finders#find)\n      # @raise [Capybara::ExpectationNotMet]      If the selector does not exist\n      #\n      def assert_ancestor(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block, Capybara::Queries::AncestorQuery) do |result, query|\n          unless result.matches_count? && (result.any? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.failure_message\n          end\n        end\n      end\n\n      def assert_no_ancestor(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block, Capybara::Queries::AncestorQuery) do |result, query|\n          if result.matches_count? && (!result.empty? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.negative_failure_message\n          end\n        end\n      end\n\n      ##\n      #\n      # Predicate version of {#assert_ancestor}\n      #\n      def has_ancestor?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_ancestor(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Predicate version of {#assert_no_ancestor}\n      #\n      def has_no_ancestor?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_no_ancestor(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Asserts that a given selector matches a sibling of the current node.\n      #\n      #     element.assert_sibling('p#foo')\n      #\n      # Accepts the same options as {#assert_selector}\n      #\n      # @param (see Capybara::Node::Finders#find)\n      # @raise [Capybara::ExpectationNotMet]      If the selector does not exist\n      #\n      def assert_sibling(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block, Capybara::Queries::SiblingQuery) do |result, query|\n          unless result.matches_count? && (result.any? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.failure_message\n          end\n        end\n      end\n\n      def assert_no_sibling(*args, &optional_filter_block)\n        _verify_selector_result(args, optional_filter_block, Capybara::Queries::SiblingQuery) do |result, query|\n          if result.matches_count? && (!result.empty? || query.expects_none?)\n            raise Capybara::ExpectationNotMet, result.negative_failure_message\n          end\n        end\n      end\n\n      ##\n      #\n      # Predicate version of {#assert_sibling}\n      #\n      def has_sibling?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_sibling(*args, options, &optional_filter_block) }\n      end\n\n      ##\n      #\n      # Predicate version of {#assert_no_sibling}\n      #\n      def has_no_sibling?(*args, **options, &optional_filter_block)\n        make_predicate(options) { assert_no_sibling(*args, options, &optional_filter_block) }\n      end\n\n      def ==(other)\n        eql?(other) || (other.respond_to?(:base) && base == other.base)\n      end\n\n    private\n\n      def extract_selector(args)\n        args.first.is_a?(Symbol) ? args.shift : session_options.default_selector\n      end\n\n      def _verify_multiple(*args, wait: nil, **options)\n        wait = session_options.default_max_wait_time if wait.nil?\n        selector = extract_selector(args)\n        synchronize(wait) do\n          args.each { |locator| yield(selector, locator, options) }\n        end\n      end\n\n      def _verify_selector_result(query_args, optional_filter_block, query_type = Capybara::Queries::SelectorQuery)\n        # query_args, query_opts = if query_args[0].is_a? Symbol\n        #   a,o = _set_query_session_options(*query_args.slice(2..))\n        #   [query_args.slice(0..1).concat(a), o]\n        # else\n        #   _set_query_session_options(*query_args)\n        # end\n        query_args, query_opts = _set_query_session_options(*query_args)\n        query = query_type.new(*query_args, **query_opts, &optional_filter_block)\n        synchronize(query.wait) do\n          yield query.resolve_for(self), query\n        end\n        true\n      end\n\n      def _verify_match_result(query_args, optional_filter_block)\n        query_args, query_opts = _set_query_session_options(*query_args)\n        query = Capybara::Queries::MatchQuery.new(*query_args, **query_opts, &optional_filter_block)\n        synchronize(query.wait) do\n          yield query.resolve_for(parent || session&.document || query_scope)\n        end\n        true\n      end\n\n      def _verify_text(type = nil, expected_text, **query_options) # rubocop:disable Style/OptionalArguments\n        query_options[:session_options] = session_options\n        query = Capybara::Queries::TextQuery.new(type, expected_text, **query_options)\n        synchronize(query.wait) do\n          yield query.resolve_for(self), query\n        end\n        true\n      end\n\n      def _set_query_session_options(*query_args)\n        query_args, query_options = query_args.dup, {}\n        # query_options = query_args.pop if query_options.empty? && query_args.last.is_a?(Hash)\n        query_options = query_args.pop if query_args.last.is_a?(Hash)\n        query_options[:session_options] = session_options\n        [query_args, query_options]\n      end\n\n      def make_predicate(options)\n        options[:wait] = 0 unless options.key?(:wait) || session_options.predicates_wait\n        yield\n      rescue Capybara::ExpectationNotMet\n        false\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/simple.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    ##\n    #\n    # A {Capybara::Node::Simple} is a simpler version of {Capybara::Node::Base} which\n    # includes only {Capybara::Node::Finders} and {Capybara::Node::Matchers} and does\n    # not include {Capybara::Node::Actions}. This type of node is returned when\n    # using {Capybara.string}.\n    #\n    # It is useful in that it does not require a session, an application or a driver,\n    # but can still use Capybara's finders and matchers on any string that contains HTML.\n    #\n    class Simple\n      include Capybara::Node::Finders\n      include Capybara::Node::Matchers\n      include Capybara::Node::DocumentMatchers\n\n      attr_reader :native\n\n      def initialize(native)\n        native = Capybara::HTML(native) if native.is_a?(String)\n        @native = native\n      end\n\n      ##\n      #\n      # @return [String]    The text of the element\n      #\n      def text(_type = nil, normalize_ws: false)\n        txt = native.text\n        normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt\n      end\n\n      ##\n      #\n      # Retrieve the given attribute\n      #\n      #     element[:title] # => HTML title attribute\n      #\n      # @param  [Symbol] name  The attribute name to retrieve\n      # @return [String]       The value of the attribute\n      #\n      def [](name)\n        attr_name = name.to_s\n        if attr_name == 'value'\n          value\n        elsif (tag_name == 'input') && (native[:type] == 'checkbox') && (attr_name == 'checked')\n          native['checked'] == 'checked'\n        else\n          native[attr_name]\n        end\n      end\n\n      ##\n      #\n      # @return [String]      The tag name of the element\n      #\n      def tag_name\n        native.node_name\n      end\n\n      ##\n      #\n      # An XPath expression describing where on the page the element can be found\n      #\n      # @return [String]      An XPath expression\n      #\n      def path\n        native.path\n      end\n\n      ##\n      #\n      # @return [String]    The value of the form element\n      #\n      def value\n        if tag_name == 'textarea'\n          native['_capybara_raw_value']\n        elsif tag_name == 'select'\n          selected_options = find_xpath('.//option[@selected]')\n          if multiple?\n            selected_options.map(&method(:option_value))\n          else\n            option_value(selected_options.first || find_xpath('.//option').first)\n          end\n        elsif tag_name == 'input' && %w[radio checkbox].include?(native[:type])\n          native[:value] || 'on'\n        else\n          native[:value]\n        end\n      end\n\n      ##\n      #\n      # Whether or not the element is visible. Does not support CSS, so\n      # the result may be inaccurate.\n      #\n      # @param  [Boolean] check_ancestors  Whether to inherit visibility from ancestors\n      # @return [Boolean]     Whether the element is visible\n      #\n      def visible?(check_ancestors = true) # rubocop:disable Style/OptionalBooleanParameter\n        return false if (tag_name == 'input') && (native[:type] == 'hidden')\n        return false if tag_name == 'template'\n\n        if check_ancestors\n          !find_xpath(VISIBILITY_XPATH)\n        else\n          # No need for an xpath if only checking the current element\n          !(native.key?('hidden') ||\n            /display:\\s?none/.match?(native[:style] || '') ||\n            %w[script head style].include?(tag_name))\n        end\n      end\n\n      ##\n      #\n      # Whether or not the element is checked.\n      #\n      # @return [Boolean]     Whether the element is checked\n      #\n      def checked?\n        native.has_attribute?('checked')\n      end\n\n      ##\n      #\n      # Whether or not the element is disabled.\n      #\n      # @return [Boolean]     Whether the element is disabled\n      def disabled?\n        native.has_attribute?('disabled') &&\n          %w[button input select textarea optgroup option menuitem fieldset].include?(tag_name)\n      end\n\n      ##\n      #\n      # Whether or not the element is selected.\n      #\n      # @return [Boolean]     Whether the element is selected\n      #\n      def selected?\n        native.has_attribute?('selected')\n      end\n\n      def multiple?\n        native.has_attribute?('multiple')\n      end\n\n      def readonly?\n        native.has_attribute?('readonly')\n      end\n\n      def synchronize(_seconds = nil)\n        yield # simple nodes don't need to wait\n      end\n\n      def allow_reload!(*)\n        # no op\n      end\n\n      ##\n      #\n      # @return [String]     The title of the document\n      def title\n        native.title\n      end\n\n      def inspect\n        %(#<Capybara::Node::Simple tag=\"#{tag_name}\" path=\"#{path}\">)\n      end\n\n      # @api private\n      def find_css(css, **_options)\n        native.css(css)\n      end\n\n      # @api private\n      def find_xpath(xpath, **_options)\n        native.xpath(xpath)\n      end\n\n      # @api private\n      def session_options\n        Capybara.session_options\n      end\n\n      # @api private\n      def initial_cache\n        {}\n      end\n\n      def ==(other)\n        eql?(other) || (other.respond_to?(:native) && native == other.native)\n      end\n\n    private\n\n      def option_value(option)\n        return nil if option.nil?\n\n        option[:value] || option.content\n      end\n\n      VISIBILITY_XPATH = XPath.generate do |x|\n        x.ancestor_or_self[\n          x.attr(:style)[x.contains('display:none') | x.contains('display: none')] |\n          x.attr(:hidden) |\n          x.qname.one_of('script', 'head') |\n          (~x.self(:summary) & XPath.parent(:details)[!XPath.attr(:open)])\n        ].boolean\n      end.to_s.freeze\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/node/whitespace_normalizer.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Node\n    ##\n    #\n    # {Capybara::Node::WhitespaceNormalizer} provides methods that\n    # help to normalize the spacing of text content inside of\n    # {Capybara::Node::Element}s by removing various unicode\n    # spacing and directional markings.\n    #\n    module WhitespaceNormalizer\n      # Unicode for NBSP, or &nbsp;\n      NON_BREAKING_SPACE = \"\\u00a0\"\n      LINE_SEPERATOR = \"\\u2028\"\n      PARAGRAPH_SEPERATOR = \"\\u2029\"\n\n      # All spaces except for NBSP\n      BREAKING_SPACES = \"[[:space:]&&[^#{NON_BREAKING_SPACE}]]\".freeze\n\n      # Whitespace we want to substitute with plain spaces\n      SQUEEZED_SPACES = \" \\n\\f\\t\\v#{LINE_SEPERATOR}#{PARAGRAPH_SEPERATOR}\".freeze\n\n      # Any whitespace at the front of text\n      LEADING_SPACES = /\\A#{BREAKING_SPACES}+/\n\n      # Any whitespace at the end of text\n      TRAILING_SPACES = /#{BREAKING_SPACES}+\\z/\n\n      # \"Invisible\" space character\n      ZERO_WIDTH_SPACE = \"\\u200b\"\n\n      # Signifies text is read left to right\n      LEFT_TO_RIGHT_MARK = \"\\u200e\"\n\n      # Signifies text is read right to left\n      RIGHT_TO_LEFT_MARK = \"\\u200f\"\n\n      # Characters we want to truncate from text\n      REMOVED_CHARACTERS = [ZERO_WIDTH_SPACE, LEFT_TO_RIGHT_MARK, RIGHT_TO_LEFT_MARK].join\n\n      # Matches multiple empty lines\n      EMPTY_LINES = /[\\ \\n]*\\n[\\ \\n]*/\n\n      ##\n      #\n      # Normalizes the spacing of a node's text to be similar to\n      # what matchers might expect.\n      #\n      # @param text [String]\n      # @return [String]\n      #\n      def normalize_spacing(text)\n        text\n          .delete(REMOVED_CHARACTERS)\n          .tr(SQUEEZED_SPACES, ' ')\n          .squeeze(' ')\n          .sub(LEADING_SPACES, '')\n          .sub(TRAILING_SPACES, '')\n          .tr(NON_BREAKING_SPACE, ' ')\n      end\n\n      ##\n      #\n      # Variant on {Capybara::Node::Normalizer#normalize_spacing} that\n      # targets the whitespace of visible elements only.\n      #\n      # @param text [String]\n      # @return [String]\n      #\n      def normalize_visible_spacing(text)\n        text\n          .squeeze(' ')\n          .gsub(EMPTY_LINES, \"\\n\")\n          .sub(LEADING_SPACES, '')\n          .sub(TRAILING_SPACES, '')\n          .tr(NON_BREAKING_SPACE, ' ')\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/active_element_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Queries\n    class ActiveElementQuery < BaseQuery\n      def initialize(**options)\n        @options = options\n        super(@options)\n      end\n\n      def resolve_for(session)\n        node = session.driver.active_element\n        [Capybara::Node::Element.new(session, node, nil, self)]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/ancestor_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Queries\n    class AncestorQuery < Capybara::Queries::SelectorQuery\n      # @api private\n      def resolve_for(node, exact = nil)\n        @child_node = node\n\n        node.synchronize do\n          scope = node.respond_to?(:session) ? node.session.current_scope : node.find(:xpath, '/*')\n          match_results = super(scope, exact)\n          ancestors = node.find_xpath(XPath.ancestor.to_s)\n                          .map(&method(:to_element))\n                          .select { |el| match_results.include?(el) }\n          Capybara::Result.new(ordered_results(ancestors), self)\n        end\n      end\n\n      def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter\n        child_query = @child_node&.instance_variable_get(:@query)\n        desc = super\n        desc += \" that is an ancestor of #{child_query.description}\" if child_query\n        desc\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/base_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Queries\n    class BaseQuery\n      COUNT_KEYS = %i[count minimum maximum between].freeze\n\n      attr_reader :options\n      attr_writer :session_options\n\n      def initialize(options)\n        @session_options = options.delete(:session_options)\n      end\n\n      def session_options\n        @session_options || Capybara.session_options\n      end\n\n      def wait\n        self.class.wait(options, session_options.default_max_wait_time)\n      end\n\n      def self.wait(options, default = Capybara.default_max_wait_time)\n        # if no value or nil for the :wait option is passed it should default to the default\n        wait = options.fetch(:wait, nil)\n        wait = default if wait.nil?\n        wait || 0\n      end\n\n      ##\n      #\n      # Checks if a count of 0 is valid for the query\n      # Returns false if query does not have any count options specified.\n      #\n      def expects_none?\n        count_specified? ? matches_count?(0) : false\n      end\n\n      ##\n      #\n      # Checks if the given count matches the query count options.\n      # Defaults to true if no count options are specified. If multiple\n      # count options exist, it tests that all conditions are met;\n      # however, if :count is specified, all other options are ignored.\n      #\n      # @param [Integer] count     The actual number. Should be coercible via Integer()\n      #\n      def matches_count?(count)\n        return (Integer(options[:count]) == count) if options[:count]\n        return false if options[:maximum] && (Integer(options[:maximum]) < count)\n        return false if options[:minimum] && (Integer(options[:minimum]) > count)\n        return false if options[:between] && !options[:between].include?(count)\n\n        true\n      end\n\n      ##\n      #\n      # Generates a failure message from the query description and count options.\n      #\n      def failure_message\n        \"expected to find #{description}\" << count_message\n      end\n\n      def negative_failure_message\n        \"expected not to find #{description}\" << count_message\n      end\n\n    private\n\n      def count_specified?\n        COUNT_KEYS.any? { |key| options.key? key }\n      end\n\n      def count_message\n        message = +''\n        count, between, maximum, minimum = options.values_at(:count, :between, :maximum, :minimum)\n        if count\n          message << \" #{occurrences count}\"\n        elsif between\n          message << \" between #{between.begin ? between.first : 1} and \" \\\n                     \"#{between.end ? between.last : 'infinite'} times\"\n        elsif maximum\n          message << \" at most #{occurrences maximum}\"\n        elsif minimum\n          message << \" at least #{occurrences minimum}\"\n        end\n        message\n      end\n\n      def occurrences(count)\n        \"#{count} #{Capybara::Helpers.declension('time', 'times', count)}\"\n      end\n\n      def assert_valid_keys\n        invalid_keys = @options.keys - valid_keys\n        return if invalid_keys.empty?\n\n        invalid_names = invalid_keys.map(&:inspect).join(', ')\n        valid_names = valid_keys.map(&:inspect).join(', ')\n        raise ArgumentError, \"Invalid option(s) #{invalid_names}, should be one of #{valid_names}\"\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/current_path_query.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'addressable/uri'\n\nmodule Capybara\n  # @api private\n  module Queries\n    class CurrentPathQuery < BaseQuery\n      def initialize(expected_path, **options, &optional_filter_block)\n        super(options)\n        @expected_path = expected_path\n        @options = {\n          url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || '').hostname.nil?,\n          ignore_query: false\n        }.merge(options)\n        @filter_block = optional_filter_block\n        assert_valid_keys\n      end\n\n      def resolves_for?(session)\n        uri = ::Addressable::URI.parse(session.current_url)\n        @actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).then do |u|\n          options[:url] ? u&.to_s : u&.request_uri\n        end\n\n        res = if @expected_path.is_a? Regexp\n          @actual_path.to_s.match?(@expected_path)\n        else\n          ::Addressable::URI.parse(@expected_path) == ::Addressable::URI.parse(@actual_path)\n        end\n\n        res && matches_filter_block?(uri)\n      end\n\n      def failure_message\n        failure_message_helper\n      end\n\n      def negative_failure_message\n        failure_message_helper(' not')\n      end\n\n    private\n\n      def matches_filter_block?(url)\n        return true unless @filter_block\n\n        @filter_block.call(url)\n      end\n\n      def failure_message_helper(negated = '')\n        verb = @expected_path.is_a?(Regexp) ? 'match' : 'equal'\n        \"expected #{@actual_path.inspect}#{negated} to #{verb} #{@expected_path.inspect}\"\n      end\n\n      def valid_keys\n        %i[wait url ignore_query]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/match_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Queries\n    class MatchQuery < Capybara::Queries::SelectorQuery\n      def visible\n        options.key?(:visible) ? super : :all\n      end\n\n    private\n\n      def assert_valid_keys\n        invalid_options = @options.keys & COUNT_KEYS\n        unless invalid_options.empty?\n          raise ArgumentError, \"Match queries don't support quantity options. Invalid keys - #{invalid_options.join(', ')}\"\n        end\n\n        super\n      end\n\n      def valid_keys\n        super - COUNT_KEYS\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/selector_query.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'matrix'\n\nmodule Capybara\n  module Queries\n    class SelectorQuery < Queries::BaseQuery\n      attr_reader :expression, :selector, :locator, :options\n\n      SPATIAL_KEYS = %i[above below left_of right_of near].freeze\n      VALID_KEYS = SPATIAL_KEYS + COUNT_KEYS +\n                   %i[text id class style visible obscured exact exact_text normalize_ws match wait filter_set focused]\n      VALID_MATCH = %i[first smart prefer_exact one].freeze\n\n      def initialize(*args,\n                     session_options:,\n                     enable_aria_label: session_options.enable_aria_label,\n                     enable_aria_role: session_options.enable_aria_role,\n                     test_id: session_options.test_id,\n                     selector_format: nil,\n                     order: nil,\n                     **options,\n                     &filter_block)\n        @resolved_node = nil\n        @resolved_count = 0\n        @options = options.dup\n        @order = order\n        @filter_cache = Hash.new { |hsh, key| hsh[key] = {} }\n\n        if @options[:text].is_a?(Regexp) && [true, false].include?(@options[:exact_text])\n          Capybara::Helpers.warn(\n            \"Boolean 'exact_text' option is not supported when 'text' option is a Regexp - ignoring\"\n          )\n        end\n\n        super(@options)\n        self.session_options = session_options\n\n        @selector = Selector.new(\n          find_selector(args[0].is_a?(Symbol) ? args.shift : args[0]),\n          config: {\n            enable_aria_label: enable_aria_label,\n            enable_aria_role: enable_aria_role,\n            test_id: test_id\n          },\n          format: selector_format\n        )\n\n        @locator = args.shift\n        @filter_block = filter_block\n\n        raise ArgumentError, \"Unused parameters passed to #{self.class.name} : #{args}\" unless args.empty?\n\n        @expression = selector.call(@locator, **@options)\n\n        warn_exact_usage\n\n        assert_valid_keys\n      end\n\n      def name; selector.name; end\n      def label; selector.label || selector.name; end\n\n      def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter\n        desc = +''\n        show_for = show_for_stage(only_applied)\n\n        if show_for[:any]\n          desc << 'visible ' if visible == :visible\n          desc << 'non-visible ' if visible == :hidden\n        end\n\n        desc << label.to_s\n        desc << \" #{locator.inspect}\" unless locator.nil?\n\n        if show_for[:any]\n          desc << \" with#{' exact' if exact_text == true} text #{options[:text].inspect}\" if options[:text]\n          desc << \" with exact text #{exact_text}\" if exact_text.is_a?(String)\n        end\n\n        desc << \" with id #{options[:id]}\" if options[:id]\n        desc << \" with classes [#{Array(options[:class]).join(',')}]\" if options[:class]\n        desc << ' that is focused' if options[:focused]\n        desc << ' that is not focused' if options[:focused] == false\n\n        desc << case options[:style]\n        when String\n          \" with style attribute #{options[:style].inspect}\"\n        when Regexp\n          \" with style attribute matching #{options[:style].inspect}\"\n        when Hash\n          \" with styles #{options[:style].inspect}\"\n        else ''\n        end\n\n        %i[above below left_of right_of near].each do |spatial_filter|\n          if options[spatial_filter] && show_for[:spatial]\n            desc << \" #{spatial_filter} #{options[spatial_filter] rescue '<ERROR>'}\" # rubocop:disable Style/RescueModifier\n          end\n        end\n\n        desc << selector.description(node_filters: show_for[:node], **options)\n\n        desc << ' that also matches the custom filter block' if @filter_block && show_for[:node]\n\n        desc << \" within #{@resolved_node.inspect}\" if describe_within?\n        if locator.is_a?(String) && locator.start_with?('#', './/', '//') && !selector.raw_locator?\n          desc << \"\\nNote: It appears you may be passing a CSS selector or XPath expression rather than a locator. \" \\\n                  \"Please see the documentation for acceptable locator values.\\n\\n\"\n        end\n        desc\n      end\n\n      def applied_description\n        description(true)\n      end\n\n      def matches_filters?(node, node_filter_errors = [])\n        return true if (@resolved_node&.== node) && options[:allow_self]\n\n        matches_locator_filter?(node) &&\n          matches_system_filters?(node) &&\n          matches_spatial_filters?(node) &&\n          matches_node_filters?(node, node_filter_errors) &&\n          matches_filter_block?(node)\n      rescue *(node.respond_to?(:session) ? node.session.driver.invalid_element_errors : [])\n        false\n      end\n\n      def visible\n        case (vis = options.fetch(:visible) { default_visibility })\n        when true then :visible\n        when false then :all\n        else vis\n        end\n      end\n\n      def exact?\n        supports_exact? ? options.fetch(:exact, session_options.exact) : false\n      end\n\n      def match\n        options.fetch(:match, session_options.match)\n      end\n\n      def xpath(exact = nil)\n        exact = exact? if exact.nil?\n        expr = apply_expression_filters(@expression)\n        expr = exact ? expr.to_xpath(:exact) : expr.to_s if expr.respond_to?(:to_xpath)\n        expr = filtered_expression(expr)\n        expr = \"(#{expr})[#{xpath_text_conditions}]\" if try_text_match_in_expression?\n        expr\n      end\n\n      def css\n        filtered_expression(apply_expression_filters(@expression))\n      end\n\n      # @api private\n      def resolve_for(node, exact = nil)\n        applied_filters.clear\n        @filter_cache.clear\n        @resolved_node = node\n        @resolved_count += 1\n\n        node.synchronize do\n          children = find_nodes_by_selector_format(node, exact).map(&method(:to_element))\n          Capybara::Result.new(ordered_results(children), self)\n        end\n      end\n\n      # @api private\n      def supports_exact?\n        return @expression.respond_to? :to_xpath if @selector.supports_exact?.nil?\n\n        @selector.supports_exact?\n      end\n\n      def failure_message\n        \"expected to find #{applied_description}\" << count_message\n      end\n\n      def negative_failure_message\n        \"expected not to find #{applied_description}\" << count_message\n      end\n\n    private\n\n      def selector_format\n        @selector.format\n      end\n\n      def matching_text\n        options[:text] || options[:exact_text]\n      end\n\n      def text_fragments\n        (text = matching_text).is_a?(String) ? text.split : []\n      end\n\n      def xpath_text_conditions\n        case (text = matching_text)\n        when String\n          text.split.map { |txt| XPath.contains(txt) }.reduce(&:&)\n        when Regexp\n          condition = XPath.current\n          condition = condition.uppercase if text.casefold?\n          Selector::RegexpDisassembler.new(text).alternated_substrings.map do |strs|\n            strs.flat_map(&:split).map { |str| condition.contains(str) }.reduce(:&)\n          end.reduce(:|)\n        end\n      end\n\n      def try_text_match_in_expression?\n        first_try? &&\n          matching_text &&\n          @resolved_node.is_a?(Capybara::Node::Base) &&\n          @resolved_node.session&.driver&.wait?\n      end\n\n      def first_try?\n        @resolved_count == 1\n      end\n\n      def show_for_stage(only_applied)\n        lambda do |stage = :any|\n          !only_applied || (stage == :any ? applied_filters.any? : applied_filters.include?(stage))\n        end\n      end\n\n      def applied_filters\n        @applied_filters ||= []\n      end\n\n      def find_selector(locator)\n        case locator\n        when Symbol then Selector[locator]\n        else Selector.for(locator)\n        end || Selector[session_options.default_selector]\n      end\n\n      def find_nodes_by_selector_format(node, exact)\n        hints = {}\n        hints[:uses_visibility] = true unless visible == :all\n        hints[:texts] = text_fragments unless selector_format == :xpath\n        hints[:styles] = options[:style] if use_default_style_filter?\n        hints[:position] = true if use_spatial_filter?\n\n        case selector_format\n        when :css\n          if node.method(:find_css).arity == 1\n            node.find_css(css)\n          else\n            node.find_css(css, **hints)\n          end\n        when :xpath\n          if node.method(:find_xpath).arity == 1\n            node.find_xpath(xpath(exact))\n          else\n            node.find_xpath(xpath(exact), **hints)\n          end\n        else\n          raise ArgumentError, \"Unknown format: #{selector_format}\"\n        end\n      end\n\n      def to_element(node)\n        if @resolved_node.is_a?(Capybara::Node::Base)\n          Capybara::Node::Element.new(@resolved_node.session, node, @resolved_node, self)\n        else\n          Capybara::Node::Simple.new(node)\n        end\n      end\n\n      def valid_keys\n        (VALID_KEYS + custom_keys).uniq\n      end\n\n      def matches_node_filters?(node, errors)\n        applied_filters << :node\n\n        unapplied_options = options.keys - valid_keys\n        @selector.with_filter_errors(errors) do\n          node_filters.all? do |filter_name, filter|\n            next true unless apply_filter?(filter)\n\n            if filter.matcher?\n              unapplied_options.select { |option_name| filter.handles_option?(option_name) }.all? do |option_name|\n                unapplied_options.delete(option_name)\n                filter.matches?(node, option_name, options[option_name], @selector)\n              end\n            elsif options.key?(filter_name)\n              unapplied_options.delete(filter_name)\n              filter.matches?(node, filter_name, options[filter_name], @selector)\n            elsif filter.default?\n              filter.matches?(node, filter_name, filter.default, @selector)\n            else\n              true\n            end\n          end\n        end\n      end\n\n      def matches_filter_block?(node)\n        return true unless @filter_block\n\n        if node.respond_to?(:session)\n          node.session.using_wait_time(0) { @filter_block.call(node) }\n        else\n          @filter_block.call(node)\n        end\n      end\n\n      def filter_set(name)\n        ::Capybara::Selector::FilterSet[name]\n      end\n\n      def node_filters\n        if options.key?(:filter_set)\n          filter_set(options[:filter_set])\n        else\n          @selector\n        end.node_filters\n      end\n\n      def expression_filters\n        filters = @selector.expression_filters\n        filters.merge filter_set(options[:filter_set]).expression_filters if options.key?(:filter_set)\n        filters\n      end\n\n      def ordered_results(results)\n        case @order\n        when :reverse\n          results.reverse\n        else\n          results\n        end\n      end\n\n      def custom_keys\n        @custom_keys ||= node_filters.keys + expression_filters.keys\n      end\n\n      def assert_valid_keys\n        unless VALID_MATCH.include?(match)\n          raise ArgumentError, \"Invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(', ')}\"\n        end\n\n        unhandled_options = @options.keys.reject do |option_name|\n          valid_keys.include?(option_name) ||\n            expression_filters.any? { |_name, ef| ef.handles_option? option_name } ||\n            node_filters.any? { |_name, nf| nf.handles_option? option_name }\n        end\n\n        return if unhandled_options.empty?\n\n        invalid_names = unhandled_options.map(&:inspect).join(', ')\n        valid_names = (valid_keys - [:allow_self]).map(&:inspect).join(', ')\n        raise ArgumentError, \"Invalid option(s) #{invalid_names}, should be one of #{valid_names}\"\n      end\n\n      def filtered_expression(expr)\n        conditions = {}\n        conditions[:id] = options[:id] if use_default_id_filter?\n        conditions[:class] = options[:class] if use_default_class_filter?\n        conditions[:style] = options[:style] if use_default_style_filter? && !options[:style].is_a?(Hash)\n        builder(expr).add_attribute_conditions(**conditions)\n      end\n\n      def use_default_id_filter?\n        options.key?(:id) && !custom_keys.include?(:id)\n      end\n\n      def use_default_class_filter?\n        options.key?(:class) && !custom_keys.include?(:class)\n      end\n\n      def use_default_style_filter?\n        options.key?(:style) && !custom_keys.include?(:style)\n      end\n\n      def use_default_focused_filter?\n        options.key?(:focused) && !custom_keys.include?(:focused)\n      end\n\n      def use_spatial_filter?\n        options.values_at(*SPATIAL_KEYS).compact.any?\n      end\n\n      def apply_expression_filters(expression)\n        unapplied_options = options.keys - valid_keys\n        expression_filters.inject(expression) do |expr, (name, ef)|\n          next expr unless apply_filter?(ef)\n\n          if ef.matcher?\n            unapplied_options.select(&ef.method(:handles_option?)).inject(expr) do |memo, option_name|\n              unapplied_options.delete(option_name)\n              ef.apply_filter(memo, option_name, options[option_name], @selector)\n            end\n          elsif options.key?(name)\n            unapplied_options.delete(name)\n            ef.apply_filter(expr, name, options[name], @selector)\n          elsif ef.default?\n            ef.apply_filter(expr, name, ef.default, @selector)\n          else\n            expr\n          end\n        end\n      end\n\n      def warn_exact_usage\n        return unless options.key?(:exact) && !supports_exact?\n\n        warn \"The :exact option only has an effect on queries using the XPath#is method. Using it with the query \\\"#{expression}\\\" has no effect.\"\n      end\n\n      def exact_text\n        options.fetch(:exact_text, session_options.exact_text)\n      end\n\n      def describe_within?\n        @resolved_node && !document?(@resolved_node) && !simple_root?(@resolved_node)\n      end\n\n      def document?(node)\n        node.is_a?(::Capybara::Node::Document)\n      end\n\n      def simple_root?(node)\n        node.is_a?(::Capybara::Node::Simple) && node.path == '/'\n      end\n\n      def apply_filter?(filter)\n        filter.format.nil? || (filter.format == selector_format)\n      end\n\n      def matches_locator_filter?(node)\n        return true unless @selector.locator_filter && apply_filter?(@selector.locator_filter)\n\n        @selector.locator_filter.matches?(node, @locator, @selector, exact: exact?)\n      end\n\n      def matches_system_filters?(node)\n        applied_filters << :system\n\n        matches_visibility_filters?(node) &&\n          matches_id_filter?(node) &&\n          matches_class_filter?(node) &&\n          matches_style_filter?(node) &&\n          matches_focused_filter?(node) &&\n          matches_text_filter?(node) &&\n          matches_exact_text_filter?(node)\n      end\n\n      def matches_spatial_filters?(node)\n        applied_filters << :spatial\n        return true unless use_spatial_filter?\n\n        node_rect = Rectangle.new(node.initial_cache[:position] || node.rect)\n\n        if options[:above]\n          el_rect = rect_cache(options[:above])\n          return false unless node_rect.above? el_rect\n        end\n\n        if options[:below]\n          el_rect = rect_cache(options[:below])\n          return false unless node_rect.below? el_rect\n        end\n\n        if options[:left_of]\n          el_rect = rect_cache(options[:left_of])\n          return false unless node_rect.left_of? el_rect\n        end\n\n        if options[:right_of]\n          el_rect = rect_cache(options[:right_of])\n          return false unless node_rect.right_of? el_rect\n        end\n\n        if options[:near]\n          return false if node == options[:near]\n\n          el_rect = rect_cache(options[:near])\n          return false unless node_rect.near? el_rect\n        end\n\n        true\n      end\n\n      def matches_id_filter?(node)\n        return true unless use_default_id_filter? && options[:id].is_a?(Regexp)\n\n        options[:id].match? node[:id]\n      end\n\n      def matches_class_filter?(node)\n        return true unless use_default_class_filter? && need_to_process_classes?\n\n        if options[:class].is_a? Regexp\n          options[:class].match? node[:class]\n        else\n          classes = (node[:class] || '').split\n          options[:class].select { |c| c.is_a? Regexp }.all? do |r|\n            classes.any? { |cls| r.match? cls }\n          end\n        end\n      end\n\n      def matches_focused_filter?(node)\n        return true unless use_default_focused_filter?\n\n        (node == node.session.active_element) == options[:focused]\n      end\n\n      def need_to_process_classes?\n        case options[:class]\n        when Regexp then true\n        when Array then options[:class].any?(Regexp)\n        else\n          false\n        end\n      end\n\n      def matches_style_filter?(node)\n        case options[:style]\n        when String, nil\n          true\n        when Regexp\n          options[:style].match? node[:style]\n        when Hash\n          matches_style?(node, options[:style])\n        end\n      end\n\n      def matches_style?(node, styles)\n        @actual_styles = node.initial_cache[:style] || node.style(*styles.keys)\n        styles.all? do |style, value|\n          if value.is_a? Regexp\n            value.match? @actual_styles[style.to_s]\n          else\n            @actual_styles[style.to_s] == value\n          end\n        end\n      end\n\n      def matches_text_filter?(node)\n        value = options[:text]\n        return true unless value\n        return matches_text_exactly?(node, value) if exact_text == true && !value.is_a?(Regexp)\n\n        regexp = value.is_a?(Regexp) ? value : Regexp.escape(value.to_s)\n        matches_text_regexp?(node, regexp)\n      end\n\n      def matches_exact_text_filter?(node)\n        case exact_text\n        when String, Regexp\n          matches_text_exactly?(node, exact_text)\n        else\n          true\n        end\n      end\n\n      def matches_visibility_filters?(node)\n        obscured = options[:obscured]\n        return (visible != :hidden) && (node.initial_cache[:visible] != false) && !node.obscured? if obscured == false\n\n        vis = case visible\n        when :visible\n          node.initial_cache[:visible] || (node.initial_cache[:visible].nil? && node.visible?)\n        when :hidden\n          # TODO: check why the 'visbile' cache spelling mistake wasn't caught in a test\n          # (node.initial_cache[:visible] == false) || (node.initial_cache[:visbile].nil? && !node.visible?)\n          (node.initial_cache[:visible] == false) || (node.initial_cache[:visible].nil? && !node.visible?)\n        else\n          true\n        end\n\n        vis && case obscured\n               when true\n                 node.obscured?\n               when false\n                 !node.obscured?\n               else\n                 true\n               end\n      end\n\n      def matches_text_exactly?(node, value)\n        regexp = value.is_a?(Regexp) ? value : /\\A#{Regexp.escape(value.to_s)}\\z/\n        matches_text_regexp(node, regexp).then { |m| m&.pre_match == '' && m&.post_match == '' }\n      end\n\n      def normalize_ws\n        options.fetch(:normalize_ws, session_options.default_normalize_ws)\n      end\n\n      def matches_text_regexp(node, regexp)\n        text_visible = visible\n        text_visible = :all if text_visible == :hidden\n        node.text(text_visible, normalize_ws: normalize_ws).match(regexp)\n      end\n\n      def matches_text_regexp?(node, regexp)\n        !matches_text_regexp(node, regexp).nil?\n      end\n\n      def default_visibility\n        @selector.default_visibility(session_options.ignore_hidden_elements, options)\n      end\n\n      def builder(expr)\n        selector.builder(expr)\n      end\n\n      def position_cache(key)\n        @filter_cache[key][:position] ||= key.rect\n      end\n\n      def rect_cache(key)\n        @filter_cache[key][:rect] ||= Rectangle.new(position_cache(key))\n      end\n\n      class Rectangle\n        attr_reader :top, :bottom, :left, :right\n\n        def initialize(position)\n          # rubocop:disable Style/RescueModifier\n          @top = position['top'] rescue position['y']\n          @bottom = position['bottom'] rescue (@top + position['height'])\n          @left = position['left'] rescue position['x']\n          @right = position['right'] rescue (@left + position['width'])\n          # rubocop:enable Style/RescueModifier\n        end\n\n        def distance(other)\n          distance = Float::INFINITY\n\n          line_segments.each do |ls1|\n            other.line_segments.each do |ls2|\n              distance = [\n                distance,\n                distance_segment_segment(*ls1, *ls2)\n              ].min\n            end\n          end\n\n          distance\n        end\n\n        def above?(other)\n          bottom <= other.top\n        end\n\n        def below?(other)\n          top >= other.bottom\n        end\n\n        def left_of?(other)\n          right <= other.left\n        end\n\n        def right_of?(other)\n          left >= other.right\n        end\n\n        def near?(other)\n          distance(other) <= 50\n        end\n\n      protected\n\n        def line_segments\n          [\n            [Vector[top, left], Vector[top, right]],\n            [Vector[top, right], Vector[bottom, left]],\n            [Vector[bottom, left], Vector[bottom, right]],\n            [Vector[bottom, right], Vector[top, left]]\n          ]\n        end\n\n      private\n\n        def distance_segment_segment(l1p1, l1p2, l2p1, l2p2)\n          # See http://geomalgorithms.com/a07-_distance.html\n          # rubocop:disable Naming/VariableName\n          u = l1p2 - l1p1\n          v = l2p2 - l2p1\n          w = l1p1 - l2p1\n\n          a = u.dot u\n          b = u.dot v\n          c = v.dot v\n\n          d = u.dot w\n          e = v.dot w\n          cap_d = (a * c) - (b**2)\n          sD = tD = cap_d\n\n          # compute the line parameters of the two closest points\n          if cap_d < Float::EPSILON # the lines are almost parallel\n            sN = 0.0 # force using point P0 on segment S1\n            sD = 1.0 # to prevent possible division by 0.0 later\n            tN = e\n            tD = c\n          else # get the closest points on the infinite lines\n            sN = (b * e) - (c * d)\n            tN = (a * e) - (b * d)\n            if sN.negative? # sc < 0 => the s=0 edge is visible\n              sN = 0\n              tN = e\n              tD = c\n            elsif sN > sD # sc > 1 => the s=1 edge is visible\n              sN = sD\n              tN = e + b\n              tD = c\n            end\n          end\n\n          if tN.negative? # tc < 0 => the t=0 edge is visible\n            tN = 0\n            # recompute sc for this edge\n            if (-d).negative?\n              sN = 0.0\n            elsif -d > a\n              sN = sD\n            else\n              sN = -d\n              sD = a\n            end\n          elsif tN > tD # tc > 1 => the t=1 edge is visible\n            tN = tD\n            # recompute sc for this edge\n            if (-d + b).negative?\n              sN = 0.0\n            elsif (-d + b) > a\n              sN = sD\n            else\n              sN = (-d + b)\n              sD = a\n            end\n          end\n\n          # finally do the division to get sc and tc\n          sc = sN.abs < Float::EPSILON ? 0.0 : sN / sD\n          tc = tN.abs < Float::EPSILON ? 0.0 : tN / tD\n\n          # difference of the two closest points\n          dP = w + (u * sc) - (v * tc)\n\n          Math.sqrt(dP.dot(dP))\n          # rubocop:enable Naming/VariableName\n        end\n      end\n\n      private_constant :Rectangle\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/sibling_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Queries\n    class SiblingQuery < SelectorQuery\n      # @api private\n      def resolve_for(node, exact = nil)\n        @sibling_node = node\n        node.synchronize do\n          scope = node.respond_to?(:session) ? node.session.current_scope : node.find(:xpath, '/*')\n          match_results = super(scope, exact)\n          siblings = node.find_xpath((XPath.preceding_sibling + XPath.following_sibling).to_s)\n                         .map(&method(:to_element))\n                         .select { |el| match_results.include?(el) }\n          Capybara::Result.new(ordered_results(siblings), self)\n        end\n      end\n\n      def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter\n        desc = super\n        sibling_query = @sibling_node&.instance_variable_get(:@query)\n        desc += \" that is a sibling of #{sibling_query.description}\" if sibling_query\n        desc\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/style_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Queries\n    class StyleQuery < BaseQuery\n      def initialize(expected_styles, session_options:, **options)\n        @expected_styles = stringify_keys(expected_styles)\n        @options = options\n        @actual_styles = {}\n        super(@options)\n        self.session_options = session_options\n\n        assert_valid_keys\n      end\n\n      def resolves_for?(node)\n        @node = node\n        @actual_styles = node.style(*@expected_styles.keys)\n        @expected_styles.all? do |style, value|\n          if value.is_a? Regexp\n            value.match? @actual_styles[style]\n          else\n            @actual_styles[style] == value\n          end\n        end\n      end\n\n      def failure_message\n        \"Expected node to have styles #{@expected_styles.inspect}. \" \\\n          \"Actual styles were #{@actual_styles.inspect}\"\n      end\n\n    private\n\n      def stringify_keys(hsh)\n        hsh.transform_keys(&:to_s)\n      end\n\n      def valid_keys\n        %i[wait]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/text_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Queries\n    class TextQuery < BaseQuery\n      def initialize(type = nil, expected_text, session_options:, **options) # rubocop:disable Style/OptionalArguments\n        @type = type.nil? ? default_type : type\n        raise ArgumentError, \"#{@type} is not a valid type for a text query\" unless valid_types.include?(@type)\n\n        @options = options\n        super(@options)\n        self.session_options = session_options\n\n        if expected_text.nil? && !exact?\n          warn 'Checking for expected text of nil is confusing and/or pointless since it will always match. ' \\\n               \"Please specify a string or regexp instead. #{Capybara::Helpers.filter_backtrace(caller)}\"\n        end\n\n        @expected_text = expected_text.is_a?(Regexp) ? expected_text : expected_text.to_s\n\n        @search_regexp = Capybara::Helpers.to_regexp(@expected_text, exact: exact?)\n\n        assert_valid_keys\n      end\n\n      def resolve_for(node)\n        @node = node\n        @actual_text = text\n        @count = @actual_text.scan(@search_regexp).size\n      end\n\n      def failure_message\n        super << build_message(true)\n      end\n\n      def negative_failure_message\n        super << build_message(false)\n      end\n\n      def description\n        if @expected_text.is_a?(Regexp)\n          \"text matching #{@expected_text.inspect}\"\n        else\n          \"#{'exact ' if exact?}text #{@expected_text.inspect}\"\n        end\n      end\n\n    private\n\n      def exact?\n        options.fetch(:exact, session_options.exact_text)\n      end\n\n      def build_message(report_on_invisible)\n        message = +''\n        unless (COUNT_KEYS & @options.keys).empty?\n          message << \" but found #{@count} #{Capybara::Helpers.declension('time', 'times', @count)}\"\n        end\n        message << \" in #{@actual_text.inspect}\"\n\n        details_message = []\n        details_message << case_insensitive_message if @node && check_case_insensitive?\n        details_message << invisible_message if @node && check_visible_text? && report_on_invisible\n        details_message.compact!\n\n        message << \". (However, #{details_message.join(' and ')}.)\" unless details_message.empty?\n        message\n      end\n\n      def case_insensitive_message\n        insensitive_regexp = Capybara::Helpers.to_regexp(@expected_text, options: Regexp::IGNORECASE)\n        insensitive_count = @actual_text.scan(insensitive_regexp).size\n        return if insensitive_count == @count\n\n        \"it was found #{occurrences insensitive_count} using a case insensitive search\"\n      end\n\n      def invisible_message\n        invisible_text = text(query_type: :all)\n        invisible_count = invisible_text.scan(@search_regexp).size\n        return if invisible_count == @count\n\n        \"it was found #{occurrences invisible_count} including non-visible text\"\n      rescue StandardError\n        # An error getting the non-visible text (if element goes out of scope) should not affect the response\n        nil\n      end\n\n      def valid_keys\n        COUNT_KEYS + %i[wait exact normalize_ws]\n      end\n\n      def valid_types\n        %i[all visible]\n      end\n\n      def check_visible_text?\n        @type == :visible\n      end\n\n      def check_case_insensitive?\n        !@expected_text.is_a?(Regexp)\n      end\n\n      def text(node: @node, query_type: @type)\n        normalize_ws = options.fetch(:normalize_ws, session_options.default_normalize_ws)\n        node.text(query_type, normalize_ws: normalize_ws)\n      end\n\n      def default_type\n        Capybara.ignore_hidden_elements || Capybara.visible_text_only ? :visible : :all\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/queries/title_query.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  module Queries\n    class TitleQuery < BaseQuery\n      def initialize(expected_title, **options)\n        @expected_title = expected_title.is_a?(Regexp) ? expected_title : expected_title.to_s\n        @options = options\n        super(@options)\n        @search_regexp = Helpers.to_regexp(@expected_title, all_whitespace: true, exact: options.fetch(:exact, false))\n        assert_valid_keys\n      end\n\n      def resolves_for?(node)\n        (@actual_title = node.title).match?(@search_regexp)\n      end\n\n      def failure_message\n        failure_message_helper\n      end\n\n      def negative_failure_message\n        failure_message_helper(' not')\n      end\n\n    private\n\n      def failure_message_helper(negated = '')\n        verb = @expected_title.is_a?(Regexp) ? 'match' : 'include'\n        \"expected #{@actual_title.inspect}#{negated} to #{verb} #{@expected_title.inspect}\"\n      end\n\n      def valid_keys\n        %i[wait exact]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/browser.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::RackTest::Browser\n  include ::Rack::Test::Methods\n\n  attr_reader :driver\n  attr_accessor :current_host\n\n  def initialize(driver)\n    @driver = driver\n    @current_fragment = nil\n  end\n\n  def app\n    driver.app\n  end\n\n  def options\n    driver.options\n  end\n\n  def visit(path, **attributes)\n    @new_visit_request = true\n    reset_cache!\n    reset_host!\n    process_and_follow_redirects(:get, path, attributes)\n  end\n\n  def refresh\n    reset_cache!\n    request(last_request.fullpath, last_request.env)\n  end\n\n  def submit(method, path, attributes, content_type: nil)\n    path = request_path if path.nil? || path.empty?\n    uri = build_uri(path)\n    uri.query = '' if method.to_s.casecmp('get').zero?\n    env = { 'HTTP_REFERER' => referer_url }\n    env['CONTENT_TYPE'] = content_type if content_type\n    process_and_follow_redirects(\n      method,\n      uri.to_s,\n      attributes,\n      env\n    )\n  end\n\n  def follow(method, path, **attributes)\n    return if fragment_or_script?(path)\n\n    process_and_follow_redirects(method, path, attributes, 'HTTP_REFERER' => referer_url)\n  end\n\n  def process_and_follow_redirects(method, path, attributes = {}, env = {})\n    @current_fragment = build_uri(path).fragment\n    process(method, path, attributes, env)\n    return unless driver.follow_redirects?\n\n    driver.redirect_limit.times do\n      if last_response.redirect?\n        if [307, 308].include? last_response.status\n          process(last_request.request_method, last_response['Location'], last_request.params, env)\n        else\n          process(:get, last_response['Location'], {}, env)\n        end\n      end\n    end\n\n    if last_response.redirect? # rubocop:disable Style/GuardClause\n      raise Capybara::InfiniteRedirectError, \"redirected more than #{driver.redirect_limit} times, check for infinite redirects.\"\n    end\n  end\n\n  def process(method, path, attributes = {}, env = {})\n    method = method.downcase\n    new_uri = build_uri(path)\n    @current_scheme, @current_host, @current_port = new_uri.select(:scheme, :host, :port)\n    @current_fragment = new_uri.fragment || @current_fragment\n    reset_cache!\n    @new_visit_request = false\n    send(method, new_uri.to_s, attributes, env.merge(options[:headers] || {}))\n  end\n\n  def build_uri(path)\n    uri = URI.parse(path)\n    base_uri = base_relative_uri_for(uri)\n\n    uri.path = base_uri.path + uri.path unless uri.absolute? || uri.path.start_with?('/')\n\n    if base_uri.absolute?\n      base_uri.merge(uri)\n    else\n      uri.scheme ||= @current_scheme\n      uri.host ||= @current_host\n      uri.port ||= @current_port unless uri.default_port == @current_port\n      uri\n    end\n  end\n\n  def current_url\n    uri = build_uri(last_request.url)\n    uri.fragment = @current_fragment if @current_fragment\n    uri.to_s\n  rescue Rack::Test::Error\n    ''\n  end\n\n  def reset_host!\n    uri = URI.parse(driver.session_options.app_host || driver.session_options.default_host)\n    @current_scheme, @current_host, @current_port = uri.select(:scheme, :host, :port)\n  end\n\n  def reset_cache!\n    @dom = nil\n  end\n\n  def dom\n    @dom ||= Capybara::HTML(html)\n  end\n\n  def find(format, selector)\n    if format == :css\n      dom.css(selector, Capybara::RackTest::CSSHandlers.new)\n    else\n      dom.xpath(selector)\n    end.map { |node| Capybara::RackTest::Node.new(self, node) }\n  end\n\n  def html\n    last_response.body\n  rescue Rack::Test::Error\n    ''\n  end\n\n  def title\n    dom.title\n  end\n\n  def last_request\n    raise Rack::Test::Error if @new_visit_request\n\n    super\n  end\n\n  def last_response\n    raise Rack::Test::Error if @new_visit_request\n\n    super\n  end\n\nprotected\n\n  def base_href\n    find(:css, 'head > base').first&.[](:href).to_s\n  end\n\n  def base_relative_uri_for(uri)\n    base_uri = URI.parse(base_href)\n    current_uri = URI.parse(safe_last_request&.url.to_s).tap do |c|\n      c.path.sub!(%r{/[^/]*$}, '/') unless uri.path.empty?\n      c.path = '/' if c.path.empty?\n    end\n\n    if [current_uri, base_uri].any?(&:absolute?)\n      current_uri.merge(base_uri)\n    else\n      base_uri.path = current_uri.path if base_uri.path.empty?\n      base_uri\n    end\n  end\n\n  def build_rack_mock_session\n    reset_host! unless current_host\n    Rack::MockSession.new(app, current_host)\n  end\n\n  def request_path\n    last_request.path\n  rescue Rack::Test::Error\n    '/'\n  end\n\n  def safe_last_request\n    last_request\n  rescue Rack::Test::Error\n    nil\n  end\n\nprivate\n\n  def fragment_or_script?(path)\n    path.gsub(/^#{Regexp.escape(request_path)}/, '').start_with?('#') || path.downcase.start_with?('javascript:')\n  end\n\n  def referer_url\n    build_uri(last_request.url).to_s\n  rescue Rack::Test::Error\n    ''\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/css_handlers.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::RackTest::CSSHandlers < BasicObject\n  include ::Kernel\n\n  def disabled(list)\n    list.find_all { |node| node.has_attribute? 'disabled' }\n  end\n\n  def enabled(list)\n    list.find_all { |node| !node.has_attribute? 'disabled' }\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rack/test'\nrequire 'rack/utils'\nrequire 'mini_mime'\nrequire 'nokogiri'\n\nclass Capybara::RackTest::Driver < Capybara::Driver::Base\n  DEFAULT_OPTIONS = {\n    respect_data_method: false,\n    follow_redirects: true,\n    redirect_limit: 5\n  }.freeze\n  attr_reader :app, :options\n\n  def initialize(app, **options)\n    raise ArgumentError, 'rack-test requires a rack application, but none was given' unless app\n\n    super()\n    @app = app\n    @options = DEFAULT_OPTIONS.merge(options)\n  end\n\n  def browser\n    @browser ||= Capybara::RackTest::Browser.new(self)\n  end\n\n  def follow_redirects?\n    @options[:follow_redirects]\n  end\n\n  def redirect_limit\n    @options[:redirect_limit]\n  end\n\n  def response\n    browser.last_response\n  end\n\n  def request\n    browser.last_request\n  end\n\n  def visit(path, **attributes)\n    browser.visit(path, **attributes)\n  end\n\n  def refresh\n    browser.refresh\n  end\n\n  def submit(method, path, attributes)\n    browser.submit(method, path, attributes)\n  end\n\n  def follow(method, path, **attributes)\n    browser.follow(method, path, attributes)\n  end\n\n  def current_url\n    browser.current_url\n  end\n\n  def response_headers\n    response.headers\n  end\n\n  def status_code\n    response.status\n  end\n\n  def find_xpath(selector)\n    browser.find(:xpath, selector)\n  end\n\n  def find_css(selector)\n    browser.find(:css, selector)\n  rescue Nokogiri::CSS::SyntaxError\n    raise unless selector.include?(' i]')\n\n    raise ArgumentError, \"This driver doesn't support case insensitive attribute matching when using CSS base selectors\"\n  end\n\n  def html\n    browser.html\n  end\n\n  def dom\n    browser.dom\n  end\n\n  def title\n    browser.title\n  end\n\n  def reset!\n    @browser = nil\n  end\n\n  def get(...); browser.get(...); end\n  def post(...); browser.post(...); end\n  def put(...); browser.put(...); end\n  def delete(...); browser.delete(...); end\n  def header(key, value); browser.header(key, value); end\n\n  def invalid_element_errors\n    [Capybara::RackTest::Errors::StaleElementReferenceError]\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/errors.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara::RackTest::Errors\n  class StaleElementReferenceError < StandardError\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/form.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::RackTest::Form < Capybara::RackTest::Node\n  # This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for\n  # the class specifically when determining whether to construct the request as multipart.\n  # That check should be based solely on the form element's 'enctype' attribute value,\n  # which should probably be provided to Rack::Test in its non-GET request methods.\n  class NilUploadedFile < Rack::Test::UploadedFile\n    def initialize # rubocop:disable Lint/MissingSuper\n      @empty_file = Tempfile.new('nil_uploaded_file')\n      @empty_file.close\n    end\n\n    def original_filename; ''; end\n    def content_type; 'application/octet-stream'; end\n    def path; @empty_file.path; end\n    def size; 0; end\n    def read; ''; end\n    def append_to(_); end\n    def set_encoding(_); end # rubocop:disable Naming/AccessorMethodName\n  end\n\n  def params(button)\n    form_element_types = %i[input select textarea button]\n    form_elements_xpath = XPath.generate do |xp|\n      xpath = xp.descendant(*form_element_types).where(!xp.attr(:form))\n      xpath += xp.anywhere(*form_element_types).where(xp.attr(:form) == native[:id]) if native[:id]\n      xpath.where(!xp.attr(:disabled))\n    end.to_s\n\n    form_elements = native.xpath(form_elements_xpath).reject { |el| submitter?(el) && (el != button.native) }\n\n    form_params = form_elements.each_with_object({}.compare_by_identity) do |field, params|\n      case field.name\n      when 'input', 'button' then add_input_param(field, params)\n      when 'select' then add_select_param(field, params)\n      when 'textarea' then add_textarea_param(field, params)\n      end\n    end\n\n    form_params.each_with_object(make_params) do |(name, value), params|\n      merge_param!(params, name, value)\n    end.to_params_hash\n\n    # form_elements.each_with_object(make_params) do |field, params|\n    #   case field.name\n    #   when 'input', 'button' then add_input_param(field, params)\n    #   when 'select' then add_select_param(field, params)\n    #   when 'textarea' then add_textarea_param(field, params)\n    #   end\n    # end.to_params_hash\n  end\n\n  def submit(button)\n    action = button&.[]('formaction') || native['action']\n    method = button&.[]('formmethod') || request_method\n    driver.submit(method, action.to_s, params(button), content_type: native['enctype'])\n  end\n\n  def multipart?\n    self[:enctype] == 'multipart/form-data'\n  end\n\nprivate\n\n  class ParamsHash < Hash\n    def to_params_hash\n      self\n    end\n  end\n\n  def request_method\n    /post/i.match?(self[:method] || '') ? :post : :get\n  end\n\n  def merge_param!(params, key, value)\n    key = key.to_s\n    if Rack::Utils.respond_to?(:default_query_parser)\n      Rack::Utils.default_query_parser.normalize_params(params, key, value, Rack::Utils.param_depth_limit)\n    else\n      Rack::Utils.normalize_params(params, key, value)\n    end\n  end\n\n  def make_params\n    if Rack::Utils.respond_to?(:default_query_parser)\n      Rack::Utils.default_query_parser.make_params\n    else\n      ParamsHash.new\n    end\n  end\n\n  def add_input_param(field, params)\n    name, value = field['name'].to_s, field['value'].to_s\n    return if name.empty?\n\n    value = case field['type']\n    when 'radio', 'checkbox'\n      return unless field['checked']\n\n      Capybara::RackTest::Node.new(driver, field).value.to_s\n    when 'file'\n      return if value.empty? && params.keys.include?(name) && Rack::Test::VERSION.to_f >= 2.0 # rubocop:disable Performance/InefficientHashSearch\n\n      if multipart?\n        file_to_upload(value)\n      else\n        File.basename(value)\n      end\n    else\n      value\n    end\n    # merge_param!(params, name, value)\n    params[name] = value\n  end\n\n  def file_to_upload(filename)\n    if filename.empty?\n      NilUploadedFile.new\n    else\n      mime_info = MiniMime.lookup_by_filename(filename)\n      Rack::Test::UploadedFile.new(filename, mime_info&.content_type&.to_s)\n    end\n  end\n\n  def add_select_param(field, params)\n    name = field['name']\n    if field.has_attribute?('multiple')\n      value = field.xpath('.//option[@selected]').map do |option|\n        # merge_param!(params, field['name'], (option['value'] || option.text).to_s)\n        (option['value'] || option.text).to_s\n      end\n      params[name] = value unless value.empty?\n    else\n      option = field.xpath('.//option[@selected]').first || field.xpath('.//option').first\n      # merge_param!(params, field['name'], (option['value'] || option.text).to_s) if option\n      params[name] = (option['value'] || option.text).to_s if option\n    end\n  end\n\n  def add_textarea_param(field, params)\n    # merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\\r?\\n/, \"\\r\\n\"))\n    params[field['name']] = field['_capybara_raw_value'].to_s.gsub(/\\r?\\n/, \"\\r\\n\")\n  end\n\n  def submitter?(el)\n    (%w[submit image].include? el['type']) || (el.name == 'button')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rack_test/node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rack_test/errors'\nrequire 'capybara/node/whitespace_normalizer'\n\nclass Capybara::RackTest::Node < Capybara::Driver::Node\n  include Capybara::Node::WhitespaceNormalizer\n\n  BLOCK_ELEMENTS = %w[p h1 h2 h3 h4 h5 h6 ol ul pre address blockquote dl div fieldset form hr noscript table].freeze\n\n  def all_text\n    normalize_spacing(native.text)\n  end\n\n  def visible_text\n    normalize_visible_spacing(displayed_text)\n  end\n\n  def [](name)\n    string_node[name]\n  end\n\n  def style(_styles)\n    raise NotImplementedError, 'The rack_test driver does not process CSS'\n  end\n\n  def value\n    string_node.value\n  end\n\n  def set(value, **options)\n    return if disabled? || readonly?\n\n    warn \"Options passed to Node#set but the RackTest driver doesn't support any - ignoring\" unless options.empty?\n\n    if value.is_a?(Array) && !multiple?\n      raise TypeError, \"Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}\"\n    end\n\n    if radio? then set_radio(value)\n    elsif checkbox? then set_checkbox(value)\n    elsif range? then set_range(value)\n    elsif input_field? then set_input(value)\n    elsif textarea? then native['_capybara_raw_value'] = value.to_s\n    end\n  end\n\n  def select_option\n    return if disabled?\n\n    deselect_options unless select_node.multiple?\n    native['selected'] = 'selected'\n  end\n\n  def unselect_option\n    raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select_node.multiple?\n\n    native.remove_attribute('selected')\n  end\n\n  def click(keys = [], **options)\n    options.delete(:offset)\n    raise ArgumentError, 'The RackTest driver does not support click options' unless keys.empty? && options.empty?\n\n    if link?\n      follow_link\n    elsif submits?\n      associated_form = form\n      Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form\n    elsif checkable?\n      set(!checked?)\n    elsif tag_name == 'label'\n      click_label\n    elsif (details = native.xpath('.//ancestor-or-self::details').last)\n      toggle_details(details)\n    end\n  end\n\n  def tag_name\n    native.node_name\n  end\n\n  def visible?\n    string_node.visible?\n  end\n\n  def checked?\n    string_node.checked?\n  end\n\n  def selected?\n    string_node.selected?\n  end\n\n  def disabled?\n    return true if string_node.disabled?\n\n    if %w[option optgroup].include? tag_name\n      find_xpath(OPTION_OWNER_XPATH)[0].disabled?\n    else\n      !find_xpath(DISABLED_BY_FIELDSET_XPATH).empty?\n    end\n  end\n\n  def readonly?\n    # readonly attribute not valid on these input types\n    return false if input_field? && %w[hidden range color checkbox radio file submit image reset button].include?(type)\n\n    super\n  end\n\n  def path\n    native.path\n  end\n\n  def find_xpath(locator, **_hints)\n    native.xpath(locator).map { |el| self.class.new(driver, el) }\n  end\n\n  def find_css(locator, **_hints)\n    native.css(locator, Capybara::RackTest::CSSHandlers.new).map { |el| self.class.new(driver, el) }\n  end\n\n  public_instance_methods(false).each do |meth_name|\n    alias_method \"unchecked_#{meth_name}\", meth_name\n    private \"unchecked_#{meth_name}\" # rubocop:disable Style/AccessModifierDeclarations\n\n    class_eval <<~METHOD, __FILE__, __LINE__ + 1\n      def #{meth_name}(...)\n        stale_check\n        method(:\"unchecked_#{meth_name}\").call(...)\n      end\n    METHOD\n  end\n\nprotected\n\n  # @api private\n  def displayed_text(check_ancestor: true)\n    if !string_node.visible?(check_ancestor)\n      ''\n    elsif native.text?\n      native\n        .text\n        .delete(REMOVED_CHARACTERS)\n        .tr(SQUEEZED_SPACES, ' ')\n        .squeeze(' ')\n    elsif native.element?\n      text = native.children.map do |child|\n        Capybara::RackTest::Node.new(driver, child).displayed_text(check_ancestor: false)\n      end.join || ''\n      text = \"\\n#{text}\\n\" if BLOCK_ELEMENTS.include?(tag_name)\n      text\n    else # rubocop:disable Lint/DuplicateBranch\n      ''\n    end\n  end\n\nprivate\n\n  def stale_check\n    raise Capybara::RackTest::Errors::StaleElementReferenceError unless native.document == driver.dom\n  end\n\n  def deselect_options\n    select_node.find_xpath('.//option[@selected]').each { |node| node.native.remove_attribute('selected') }\n  end\n\n  def string_node\n    @string_node ||= Capybara::Node::Simple.new(native)\n  end\n\n  # a reference to the select node if this is an option node\n  def select_node\n    find_xpath('./ancestor::select[1]').first\n  end\n\n  def type\n    native[:type]\n  end\n\n  def form\n    if native[:form]\n      native.xpath(\"//form[@id='#{native[:form]}']\")\n    else\n      native.ancestors('form')\n    end.first\n  end\n\n  def set_radio(_value) # rubocop:disable Naming/AccessorMethodName\n    other_radios_xpath = XPath.generate { |xp| xp.anywhere(:input)[xp.attr(:name) == self[:name]] }.to_s\n    driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute('checked') }\n    native['checked'] = 'checked'\n  end\n\n  def set_checkbox(value) # rubocop:disable Naming/AccessorMethodName\n    if value && !native['checked']\n      native['checked'] = 'checked'\n    elsif !value && native['checked']\n      native.remove_attribute('checked')\n    end\n  end\n\n  def set_range(value) # rubocop:disable Naming/AccessorMethodName\n    min, max, step = (native['min'] || 0).to_f, (native['max'] || 100).to_f, (native['step'] || 1).to_f\n    value = value.to_f\n    value = value.clamp(min, max)\n    value = (((value - min) / step).round * step) + min\n    native['value'] = value.clamp(min, max)\n  end\n\n  def set_input(value) # rubocop:disable Naming/AccessorMethodName\n    if text_or_password? && attribute_is_not_blank?(:maxlength)\n      # Browser behavior for maxlength=\"0\" is inconsistent, so we stick with\n      # Firefox, allowing no input\n      value = value.to_s[0...self[:maxlength].to_i]\n    end\n    if value.is_a?(Array) # Assert multiple attribute is present\n      value.each do |val|\n        new_native = native.clone\n        new_native.remove_attribute('value')\n        native.add_next_sibling(new_native)\n        new_native['value'] = val.to_s\n      end\n      native.remove\n    else\n      value.to_s.tap do |set_value|\n        if set_value.end_with?(\"\\n\") && (form&.css('input, textarea')&.count == 1) # rubocop:disable Style/CollectionQuerying\n          native['value'] = set_value.to_s.chop\n          Capybara::RackTest::Form.new(driver, form).submit(self)\n        else\n          native['value'] = set_value\n        end\n      end\n    end\n  end\n\n  def attribute_is_not_blank?(attribute)\n    self[attribute] && !self[attribute].empty?\n  end\n\n  def follow_link\n    method = self['data-method'] || self['data-turbo-method'] if driver.options[:respect_data_method]\n    method ||= :get\n    driver.follow(method, self[:href].to_s)\n  end\n\n  def click_label\n    labelled_control = if native[:for]\n      find_xpath(\"//input[@id='#{native[:for]}']\")\n    else\n      find_xpath('.//input')\n    end.first\n\n    labelled_control.set(!labelled_control.checked?) if checkbox_or_radio?(labelled_control)\n  end\n\n  def toggle_details(details = nil)\n    details ||= native.xpath('.//ancestor-or-self::details').last\n    return unless details\n\n    if details.has_attribute?('open')\n      details.remove_attribute('open')\n    else\n      details.set_attribute('open', 'open')\n    end\n  end\n\n  def link?\n    tag_name == 'a' && !self[:href].nil?\n  end\n\n  def submits?\n    (tag_name == 'input' && %w[submit image].include?(type)) || (tag_name == 'button' && [nil, 'submit'].include?(type))\n  end\n\n  def checkable?\n    tag_name == 'input' && %w[checkbox radio].include?(type)\n  end\n\nprotected\n\n  def checkbox_or_radio?(field = self)\n    field&.checkbox? || field&.radio?\n  end\n\n  def checkbox?\n    input_field? && type == 'checkbox'\n  end\n\n  def radio?\n    input_field? && type == 'radio'\n  end\n\n  def text_or_password?\n    input_field? && %w[text password].include?(type)\n  end\n\n  def input_field?\n    tag_name == 'input'\n  end\n\n  def textarea?\n    tag_name == 'textarea'\n  end\n\n  def range?\n    input_field? && type == 'range'\n  end\n\n  OPTION_OWNER_XPATH = XPath.parent(:optgroup, :select, :datalist).to_s.freeze\n  DISABLED_BY_FIELDSET_XPATH = XPath.generate do |x|\n    x.parent(:fieldset)[\n      XPath.attr(:disabled)\n    ] + x.ancestor[\n      ~x.self(:legend) |\n      x.preceding_sibling(:legend)\n    ][\n      x.parent(:fieldset)[\n        x.attr(:disabled)\n      ]\n    ]\n  end.to_s.freeze\nend\n"
  },
  {
    "path": "lib/capybara/rails.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/dsl'\n\nCapybara.app = Rack::Builder.new do\n  map '/' do\n    run Rails.application\n  end\nend.to_app\n\nCapybara.save_path = Rails.root.join('tmp/capybara')\n\n# Override default rack_test driver to respect data-method attributes.\nCapybara.register_driver :rack_test do |app|\n  Capybara::RackTest::Driver.new(app, respect_data_method: true)\nend\n"
  },
  {
    "path": "lib/capybara/registration_container.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  # @api private\n  class RegistrationContainer\n    def names\n      @registered.keys\n    end\n\n    def [](name)\n      @registered[name]\n    end\n\n    def []=(name, value)\n      Capybara::Helpers.warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'\n      @registered[name] = value\n    end\n\n    def method_missing(method_name, ...)\n      if @registered.respond_to?(method_name)\n        Capybara::Helpers.warn \"DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement\"\n        return @registered.public_send(method_name, ...)\n      end\n      super\n    end\n\n    def respond_to_missing?(method_name, include_all)\n      @registered.respond_to?(method_name) || super\n    end\n\n  private\n\n    def initialize\n      @registered = {}\n    end\n\n    def register(name, block)\n      @registered[name] = block\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/registrations/drivers.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.register_driver :rack_test do |app|\n  Capybara::RackTest::Driver.new(app)\nend\n\nCapybara.register_driver :selenium do |app|\n  Capybara::Selenium::Driver.new(app)\nend\n\nCapybara.register_driver :selenium_headless do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  browser_options = Selenium::WebDriver::Firefox::Options.new.tap do |opts|\n    opts.add_argument '-headless'\n  end\n  Capybara::Selenium::Driver.new(app, **{ :browser => :firefox, options_key => browser_options })\nend\n\nCapybara.register_driver :selenium_chrome do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts|\n    # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary\n    opts.add_argument('--disable-site-isolation-trials')\n  end\n\n  Capybara::Selenium::Driver.new(app, **{ :browser => :chrome, options_key => browser_options })\nend\n\nCapybara.register_driver :selenium_chrome_headless do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts|\n    opts.add_argument('--headless=new')\n    opts.add_argument('--disable-gpu') if Gem.win_platform?\n    # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary\n    opts.add_argument('--disable-site-isolation-trials')\n\n    # https://github.com/teamcapybara/capybara/issues/2796#issuecomment-2678172710\n    opts.add_argument('disable-background-timer-throttling')\n    opts.add_argument('disable-backgrounding-occluded-windows')\n    opts.add_argument('disable-renderer-backgrounding')\n  end\n\n  Capybara::Selenium::Driver.new(app, **{ :browser => :chrome, options_key => browser_options })\nend\n"
  },
  {
    "path": "lib/capybara/registrations/patches/puma_ssl.rb",
    "content": "# frozen_string_literal: true\n\nmodule Puma\n  module MiniSSL\n    class Socket\n      def read_nonblock(size, *_)\n        wait_states = %i[wait_readable wait_writable]\n\n        loop do\n          output = engine_read_all\n          return output if output\n\n          data = @socket.read_nonblock(size, exception: false)\n          raise IO::EAGAINWaitReadable if wait_states.include? data\n          return nil if data.nil?\n\n          @engine.inject(data)\n          output = engine_read_all\n\n          return output if output\n\n          while (neg_data = @engine.extract)\n            @socket.write neg_data\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/registrations/servers.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.register_server :default do |app, port, _host|\n  Capybara.run_default_server(app, port)\nend\n\nCapybara.register_server :webrick do |app, port, host, **options|\n  base_class = begin\n    require 'rack/handler/webrick'\n    Rack\n  rescue LoadError\n    # Rack 3 separated out the webrick handle - no way test currently in Capybaras automated\n    # tests due to Sinatra not yet supporting Rack 3 - experimental\n    require 'rackup/handler/webrick'\n    Rackup\n  end\n  options = { Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log.new(nil, 0) }.merge(options)\n  base_class::Handler::WEBrick.run(app, **options)\nend\n\nCapybara.register_server :puma do |app, port, host, **options| # rubocop:disable Metrics/BlockLength\n  begin\n    require 'rackup'\n  rescue LoadError # rubocop:disable Lint/SuppressedException\n  end\n  begin\n    require 'rack/handler/puma'\n  rescue LoadError\n    raise LoadError, 'Capybara is unable to load `puma` for its server, please add `puma` to your project or specify a different server via something like `Capybara.server = :webrick`.'\n  end\n  puma_rack_handler = defined?(Rackup::Handler::Puma) ? Rackup::Handler::Puma : Rack::Handler::Puma\n\n  unless puma_rack_handler.respond_to?(:config)\n    raise LoadError, 'Capybara requires `puma` version 3.8.0 or higher, please upgrade `puma` or register and specify your own server block'\n  end\n\n  # If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.\n  # Therefore construct and run the Server instance ourselves.\n  # puma_rack_handler.run(app, { Host: host, Port: port, Threads: \"0:4\", workers: 0, daemon: false }.merge(options))\n  default_options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false }\n  options = default_options.merge(options)\n\n  conf = puma_rack_handler.config(app, options)\n  conf.clamp\n\n  puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)\n  require_relative 'patches/puma_ssl' if Gem::Requirement.new('>=4.0.0', '< 4.1.0').satisfied_by?(puma_ver)\n\n  logger = (defined?(Puma::LogWriter) ? Puma::LogWriter : Puma::Events).then do |cls|\n    conf.options[:Silent] ? cls.strings : cls.stdio\n  end\n  conf.options[:log_writer] = logger\n\n  logger.log 'Capybara starting Puma...'\n  logger.log \"* Version #{Puma::Const::PUMA_VERSION}, codename: #{Puma::Const::CODE_NAME}\"\n  logger.log \"* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}\"\n\n  Puma::Server.new(\n    conf.app,\n    defined?(Puma::LogWriter) ? nil : logger,\n    conf.options\n  ).tap do |s|\n    s.binder.parse conf.options[:binds], (s.log_writer rescue s.events) # rubocop:disable Style/RescueModifier\n    s.min_threads, s.max_threads = conf.options[:min_threads], conf.options[:max_threads] if s.respond_to? :min_threads=\n  end.run.join\nend\n"
  },
  {
    "path": "lib/capybara/result.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'forwardable'\n\nmodule Capybara\n  ##\n  # A {Capybara::Result} represents a collection of {Capybara::Node::Element} on the page. It is possible to interact with this\n  # collection similar to an Array because it implements Enumerable and offers the following Array methods through delegation:\n  #\n  # * \\[\\]\n  # * each()\n  # * at()\n  # * size()\n  # * count()\n  # * length()\n  # * first()\n  # * last()\n  # * empty?()\n  # * values_at()\n  # * sample()\n  #\n  # @see Capybara::Node::Element\n  #\n  class Result\n    include Enumerable\n    extend Forwardable\n\n    def initialize(elements, query)\n      @elements = elements\n      @result_cache = []\n      @filter_errors = []\n      @results_enum = lazy_select_elements { |node| query.matches_filters?(node, @filter_errors) }\n      @query = query\n      @allow_reload = false\n    end\n\n    def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample, :to_ary\n\n    alias index find_index\n\n    def each(&block)\n      return enum_for(:each) unless block\n\n      @result_cache.each(&block)\n      loop do\n        next_result = @results_enum.next\n        add_to_cache(next_result)\n        yield next_result\n      end\n      self\n    end\n\n    def [](*args)\n      idx, length = args\n      max_idx = case idx\n      when Integer\n        if idx.negative?\n          nil\n        else\n          length.nil? ? idx : idx + length - 1\n        end\n      when Range\n        # idx.max is broken with beginless ranges\n        # idx.end && idx.max # endless range will have end == nil\n        max = idx.end\n        max = nil if max&.negative?\n        max -= 1 if max && idx.exclude_end?\n        max\n      end\n\n      if max_idx.nil?\n        full_results[*args]\n      else\n        load_up_to(max_idx + 1)\n        @result_cache[*args]\n      end\n    end\n    alias :at :[]\n\n    def empty?\n      !any?\n    end\n\n    def compare_count\n      return 0 unless @query\n\n      count, min, max, between = @query.options.values_at(:count, :minimum, :maximum, :between)\n\n      # Only check filters for as many elements as necessary to determine result\n      if count && (count = Integer(count))\n        return load_up_to(count + 1) <=> count\n      end\n\n      return -1 if min && (min = Integer(min)) && (load_up_to(min) < min)\n\n      return 1 if max && (max = Integer(max)) && (load_up_to(max + 1) > max)\n\n      if between\n        min, max = (between.begin && between.min) || 1, between.end\n        max -= 1 if max && between.exclude_end?\n\n        size = load_up_to(max ? max + 1 : min)\n        return size <=> min unless between.include?(size)\n      end\n\n      0\n    end\n\n    def matches_count?\n      compare_count.zero?\n    end\n\n    def failure_message\n      message = @query.failure_message\n      if count.zero?\n        message << ' but there were no matches'\n      else\n        message << \", found #{count} #{Capybara::Helpers.declension('match', 'matches', count)}: \" \\\n                << full_results.map { |r| r.text.inspect }.join(', ')\n      end\n      unless rest.empty?\n        elements = rest.map { |el| el.text rescue '<<ERROR>>' }.map(&:inspect).join(', ') # rubocop:disable Style/RescueModifier\n        message << '. Also found ' << elements << ', which matched the selector but not all filters. '\n        message << @filter_errors.join('. ') if (rest.size == 1) && count.zero?\n      end\n      message\n    end\n\n    def negative_failure_message\n      failure_message.sub(/(to find)/, 'not \\1')\n    end\n\n    def unfiltered_size\n      @elements.length\n    end\n\n    ##\n    # @api private\n    #\n    def allow_reload!\n      @allow_reload = true\n      self\n    end\n\n  private\n\n    def add_to_cache(elem)\n      elem.allow_reload!(@result_cache.size) if @allow_reload\n      @result_cache << elem\n    end\n\n    def load_up_to(num)\n      loop do\n        break if @result_cache.size >= num\n\n        add_to_cache(@results_enum.next)\n      end\n      @result_cache.size\n    end\n\n    def full_results\n      loop { @result_cache << @results_enum.next }\n      @result_cache\n    end\n\n    def rest\n      @rest ||= @elements - full_results\n    end\n\n    if RUBY_PLATFORM == 'java'\n      # JRuby < 9.2.8.0 has an issue with lazy enumerators which\n      # causes a concurrency issue with network requests here\n      # https://github.com/jruby/jruby/issues/4212\n      # while JRuby >= 9.2.8.0 leaks threads when using lazy enumerators\n      # https://github.com/teamcapybara/capybara/issues/2349\n      # so disable the use and JRuby users will need to pay a performance penalty\n      def lazy_select_elements(&block)\n        @elements.select(&block).to_enum # non-lazy evaluation\n      end\n    else\n      def lazy_select_elements(&block)\n        @elements.lazy.select(&block)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/features.rb",
    "content": "# frozen_string_literal: true\n\nRSpec.shared_context 'Capybara Features', capybara_feature: true do\n  instance_eval do\n    alias background before\n    alias given let\n    alias given! let!\n  end\nend\n\n# ensure shared_context is included if default shared_context_metadata_behavior is changed\nRSpec.configure do |config|\n  config.include_context 'Capybara Features', capybara_feature: true if config.respond_to?(:include_context)\nend\n\nRSpec.configure do |config|\n  config.alias_example_group_to :feature, :capybara_feature, type: :feature\n  config.alias_example_group_to :xfeature, :capybara_feature, type: :feature, skip: 'Temporarily disabled with xfeature'\n  config.alias_example_group_to :ffeature, :capybara_feature, :focus, type: :feature\n  config.alias_example_to :scenario\n  config.alias_example_to :xscenario, skip: 'Temporarily disabled with xscenario'\n  config.alias_example_to :fscenario, :focus\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matcher_proxies.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module RSpecMatcherProxies\n    def all(*args, **kwargs, &block)\n      if defined?(::RSpec::Matchers::BuiltIn::All) && args.first.respond_to?(:matches?)\n        ::RSpec::Matchers::BuiltIn::All.new(*args)\n      else\n        find_all(*args, **kwargs, &block)\n      end\n    end\n\n    def within(*args, **kwargs, &block)\n      if block\n        within_element(*args, **kwargs, &block)\n      else\n        be_within(*args)\n      end\n    end\n  end\nend\n\nif RUBY_ENGINE == 'jruby'\n  # :nocov:\n  module Capybara::DSL\n    class << self\n      remove_method :included\n\n      def included(base)\n        warn 'including Capybara::DSL in the global scope is not recommended!' if base == Object\n        if defined?(::RSpec::Matchers) && base.include?(::RSpec::Matchers)\n          base.send(:include, ::Capybara::RSpecMatcherProxies)\n        end\n        super\n      end\n    end\n  end\n\n  if defined?(RSpec::Matchers)\n    module ::RSpec::Matchers\n      def self.included(base)\n        base.send(:include, ::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)\n        super\n      end\n    end\n  end\n  # :nocov:\nelse\n  module Capybara::DSLRSpecProxyInstaller\n    module ClassMethods\n      def included(base)\n        base.include(::Capybara::RSpecMatcherProxies) if defined?(::RSpec::Matchers) && base.include?(::RSpec::Matchers)\n        super\n      end\n    end\n\n    def self.prepended(base)\n      class << base\n        prepend ClassMethods\n      end\n    end\n  end\n\n  module Capybara::RSpecMatcherProxyInstaller\n    module ClassMethods\n      def included(base)\n        base.include(::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)\n        super\n      end\n    end\n\n    def self.prepended(base)\n      class << base\n        prepend ClassMethods\n      end\n    end\n  end\n\n  Capybara::DSL.prepend Capybara::DSLRSpecProxyInstaller\n\n  RSpec::Matchers.prepend Capybara::RSpecMatcherProxyInstaller if defined?(RSpec::Matchers)\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/compound'\nrequire 'capybara/rspec/matchers/count_sugar'\nrequire 'capybara/rspec/matchers/spatial_sugar'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class Base\n        include ::Capybara::RSpecMatchers::Matchers::Compound if defined?(::Capybara::RSpecMatchers::Matchers::Compound)\n\n        attr_reader :failure_message, :failure_message_when_negated\n\n        def initialize(*args, **kw_args, &filter_block)\n          @args = args.dup\n          @kw_args = kw_args || {}\n          @filter_block = filter_block\n        end\n\n      private\n\n        def session_query_args\n          # if @args.last.is_a? Hash\n          #   @args.last[:session_options] = session_options\n          # else\n          #   @args.push(session_options: session_options)\n          # end\n          @args\n        end\n\n        def session_query_options\n          @kw_args[:session_options] = session_options\n          @kw_args\n        end\n\n        def session_options\n          @context_el ||= nil\n          if @context_el.respond_to? :session_options\n            @context_el.session_options\n          elsif @context_el.respond_to? :current_scope\n            @context_el.current_scope.session_options\n          else\n            Capybara.session_options\n          end\n        end\n      end\n\n      class WrappedElementMatcher < Base\n        def matches?(actual, &filter_block)\n          @filter_block ||= filter_block\n          element_matches?(wrap(actual))\n        rescue Capybara::ExpectationNotMet => e\n          @failure_message = e.message\n          false\n        end\n\n        def does_not_match?(actual, &filter_block)\n          @filter_block ||= filter_block\n          element_does_not_match?(wrap(actual))\n        rescue Capybara::ExpectationNotMet => e\n          @failure_message_when_negated = e.message\n          false\n        end\n\n      private\n\n        def wrap(actual)\n          actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)\n          @context_el = if actual.respond_to?(:has_selector?)\n            actual\n          else\n            Capybara.string(actual.to_s)\n          end\n        end\n      end\n\n      class CountableWrappedElementMatcher < WrappedElementMatcher\n        include ::Capybara::RSpecMatchers::CountSugar\n        include ::Capybara::RSpecMatchers::SpatialSugar\n      end\n\n      class NegatedMatcher\n        include ::Capybara::RSpecMatchers::Matchers::Compound if defined?(::Capybara::RSpecMatchers::Matchers::Compound)\n\n        def initialize(matcher)\n          super()\n          @matcher = matcher\n        end\n\n        def matches?(actual, &filter_block)\n          @matcher.does_not_match?(actual, &filter_block)\n        end\n\n        def does_not_match?(actual, &filter_block)\n          @matcher.matches?(actual, &filter_block)\n        end\n\n        def description\n          \"not #{@matcher.description}\"\n        end\n\n        def failure_message\n          @matcher.failure_message_when_negated\n        end\n\n        def failure_message_when_negated\n          @matcher.failure_message\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/become_closed.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class BecomeClosed\n        def initialize(options)\n          @options = options\n        end\n\n        def matches?(window)\n          @window = window\n          @wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)\n          timer = Capybara::Helpers.timer(expire_in: @wait_time)\n          while window.exists?\n            return false if timer.expired?\n\n            sleep 0.01\n          end\n          true\n        end\n\n        def failure_message\n          \"expected #{@window.inspect} to become closed after #{@wait_time} seconds\"\n        end\n\n        def failure_message_when_negated\n          \"expected #{@window.inspect} not to become closed after #{@wait_time} seconds\"\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/compound.rb",
    "content": "# frozen_string_literal: true\n\nif defined?(RSpec::Expectations::Version)\n  module Capybara\n    module RSpecMatchers\n      module Matchers\n        module Compound\n          include ::RSpec::Matchers::Composable\n\n          def and(matcher)\n            And.new(self, matcher)\n          end\n\n          def and_then(matcher)\n            ::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher)\n          end\n\n          def or(matcher)\n            Or.new(self, matcher)\n          end\n\n          class CapybaraEvaluator\n            def initialize(actual)\n              @actual = actual\n              @match_results = Hash.new { |hsh, matcher| hsh[matcher] = matcher.matches?(@actual) }\n            end\n\n            def matcher_matches?(matcher)\n              @match_results[matcher]\n            end\n\n            def reset\n              @match_results.clear\n            end\n          end\n\n          # @api private\n          module Synchronizer\n            def match(_expected, actual)\n              @evaluator = CapybaraEvaluator.new(actual)\n              syncer = sync_element(actual)\n              begin\n                syncer.synchronize do\n                  @evaluator.reset\n                  raise ::Capybara::ElementNotFound unless synchronized_match?\n\n                  true\n                end\n              rescue StandardError\n                false\n              end\n            end\n\n            def sync_element(el)\n              if el.respond_to? :synchronize\n                el\n              elsif el.respond_to? :current_scope\n                el.current_scope\n              else\n                Capybara.string(el)\n              end\n            end\n          end\n\n          class And < ::RSpec::Matchers::BuiltIn::Compound::And\n            include Synchronizer\n\n          private\n\n            def synchronized_match?\n              [matcher_1_matches?, matcher_2_matches?].all?\n            end\n          end\n\n          class Or < ::RSpec::Matchers::BuiltIn::Compound::Or\n            include Synchronizer\n\n          private\n\n            def synchronized_match?\n              [matcher_1_matches?, matcher_2_matches?].any?\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/count_sugar.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module RSpecMatchers\n    module CountSugar\n      def once; exactly(1); end\n      def twice; exactly(2); end\n      def thrice; exactly(3); end\n\n      def exactly(number)\n        options[:count] = number\n        self\n      end\n\n      def at_most(number)\n        options[:maximum] = number\n        self\n      end\n\n      def at_least(number)\n        options[:minimum] = number\n        self\n      end\n\n      def times\n        self\n      end\n\n    private\n\n      def options\n        # (@args.last.is_a?(Hash) ? @args : @args.push({})).last\n        @kw_args\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_ancestor.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveAncestor < CountableWrappedElementMatcher\n        def element_matches?(el)\n          el.assert_ancestor(*@args, **session_query_options, &@filter_block)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_ancestor(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description\n          \"have ancestor #{query.description}\"\n        end\n\n        def query\n          # @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, &@filter_block)\n          @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, **session_query_options, &@filter_block)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_current_path.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveCurrentPath < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_current_path(current_path, **@kw_args, &@filter_block)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_current_path(current_path, **@kw_args, &@filter_block)\n        end\n\n        def description\n          \"have current path #{current_path.inspect}\"\n        end\n\n      private\n\n        def current_path\n          @args.first\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_selector.rb",
    "content": "# frozen_string_literal: true\n\n# rubocop:disable Naming/PredicatePrefix\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveSelector < CountableWrappedElementMatcher\n        def initialize(*args, **kw_args, &filter_block)\n          super\n          return unless (@args.size < 2) && @kw_args.keys.any?(String)\n\n          @args.push(@kw_args)\n          @kw_args = {}\n        end\n\n        def element_matches?(el)\n          el.assert_selector(*@args, **session_query_options, &@filter_block)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_selector(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description = \"have #{query.description}\"\n\n        def query\n          @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)\n        end\n      end\n\n      class HaveAllSelectors < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_all_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def does_not_match?(_actual)\n          raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'\n        end\n\n        def description = 'have all selectors'\n      end\n\n      class HaveNoSelectors < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def does_not_match?(_actual)\n          raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'\n        end\n\n        def description = 'have no selectors'\n      end\n\n      class HaveAnySelectors < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_any_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def does_not_match?(el)\n          el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description = 'have any selectors'\n      end\n    end\n  end\nend\n\n# rubocop:enable Naming/PredicatePrefix\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_sibling.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveSibling < CountableWrappedElementMatcher\n        def element_matches?(el)\n          el.assert_sibling(*@args, **session_query_options, &@filter_block)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_sibling(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description\n          \"have sibling #{query.description}\"\n        end\n\n        def query\n          @query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, **session_query_options, &@filter_block)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_text.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveText < CountableWrappedElementMatcher\n        def element_matches?(el)\n          el.assert_text(*@args, **@kw_args)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_text(*@args, **@kw_args)\n        end\n\n        def description\n          \"have text #{format(text)}\"\n        end\n\n        def format(content)\n          content.inspect\n        end\n\n      private\n\n        def text\n          @args[0].is_a?(Symbol) ? @args[1] : @args[0]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/have_title.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class HaveTitle < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_title(*@args, **@kw_args)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_no_title(*@args, **@kw_args)\n        end\n\n        def description\n          \"have title #{title.inspect}\"\n        end\n\n      private\n\n        def title\n          @args.first\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/match_selector.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/have_selector'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class MatchSelector < HaveSelector\n        def element_matches?(el)\n          el.assert_matches_selector(*@args, **session_query_options, &@filter_block)\n        end\n\n        def element_does_not_match?(el)\n          el.assert_not_matches_selector(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description\n          \"match #{query.description}\"\n        end\n\n        def query\n          @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, **session_query_options, &@filter_block)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/match_style.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/base'\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      class MatchStyle < WrappedElementMatcher\n        def initialize(styles = nil, **kw_args, &filter_block)\n          styles, kw_args = kw_args, {} if styles.nil?\n          super(styles, **kw_args, &filter_block)\n        end\n\n        def element_matches?(el)\n          el.assert_matches_style(*@args, **@kw_args)\n        end\n\n        def does_not_match?(_actual)\n          raise ArgumentError, 'The match_style matcher does not support use with not_to/should_not'\n        end\n\n        def description\n          'match style'\n        end\n      end\n    end\n  end\nend\n\nmodule Capybara\n  module RSpecMatchers\n    module Matchers\n      ##\n      # @deprecated\n      class HaveStyle < MatchStyle\n        def initialize(*args, **kw_args, &filter_block)\n          warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'\n          super\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers/spatial_sugar.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module RSpecMatchers\n    module SpatialSugar\n      def above(el)\n        options[:above] = el\n        self\n      end\n\n      def below(el)\n        options[:below] = el\n        self\n      end\n\n      def left_of(el)\n        options[:left_of] = el\n        self\n      end\n\n      def right_of(el)\n        options[:right_of] = el\n        self\n      end\n\n      def near(el)\n        options[:near] = el\n        self\n      end\n\n    private\n\n      def options\n        # (@args.last.is_a?(Hash) ? @args : @args.push({})).last\n        @kw_args\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec/matchers.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/rspec/matchers/have_selector'\nrequire 'capybara/rspec/matchers/have_ancestor'\nrequire 'capybara/rspec/matchers/have_sibling'\nrequire 'capybara/rspec/matchers/match_selector'\nrequire 'capybara/rspec/matchers/have_current_path'\nrequire 'capybara/rspec/matchers/match_style'\nrequire 'capybara/rspec/matchers/have_text'\nrequire 'capybara/rspec/matchers/have_title'\nrequire 'capybara/rspec/matchers/become_closed'\n\nmodule Capybara\n  module RSpecMatchers\n    # RSpec matcher for whether the element(s) matching a given selector exist.\n    #\n    # @see Capybara::Node::Matchers#assert_selector\n    def have_selector(...)\n      Matchers::HaveSelector.new(...)\n    end\n\n    # RSpec matcher for whether the element(s) matching a group of selectors exist.\n    #\n    # @see Capybara::Node::Matchers#assert_all_of_selectors\n    def have_all_of_selectors(...)\n      Matchers::HaveAllSelectors.new(...)\n    end\n\n    # RSpec matcher for whether no element(s) matching a group of selectors exist.\n    #\n    # @see Capybara::Node::Matchers#assert_none_of_selectors\n    def have_none_of_selectors(...)\n      Matchers::HaveNoSelectors.new(...)\n    end\n\n    # RSpec matcher for whether the element(s) matching any of a group of selectors exist.\n    #\n    # @see Capybara::Node::Matchers#assert_any_of_selectors\n    def have_any_of_selectors(...)\n      Matchers::HaveAnySelectors.new(...)\n    end\n\n    # RSpec matcher for whether the current element matches a given selector.\n    #\n    # @see Capybara::Node::Matchers#assert_matches_selector\n    def match_selector(...)\n      Matchers::MatchSelector.new(...)\n    end\n\n    %i[css xpath].each do |selector|\n      define_method \"have_#{selector}\" do |expr, **options, &optional_filter_block|\n        Matchers::HaveSelector.new(selector, expr, **options, &optional_filter_block)\n      end\n\n      define_method \"match_#{selector}\" do |expr, **options, &optional_filter_block|\n        Matchers::MatchSelector.new(selector, expr, **options, &optional_filter_block)\n      end\n    end\n\n    # @!method have_xpath(xpath, **options, &optional_filter_block)\n    #   RSpec matcher for whether elements(s) matching a given xpath selector exist.\n    #\n    #   @see Capybara::Node::Matchers#has_xpath?\n\n    # @!method have_css(css, **options, &optional_filter_block)\n    #   RSpec matcher for whether elements(s) matching a given css selector exist\n    #\n    #   @see Capybara::Node::Matchers#has_css?\n\n    # @!method match_xpath(xpath, **options, &optional_filter_block)\n    #   RSpec matcher for whether the current element matches a given xpath selector.\n    #\n    #   @see Capybara::Node::Matchers#matches_xpath?\n\n    # @!method match_css(css, **options, &optional_filter_block)\n    #   RSpec matcher for whether the current element matches a given css selector.\n    #\n    #   @see Capybara::Node::Matchers#matches_css?\n\n    %i[link button field select table element].each do |selector|\n      define_method \"have_#{selector}\" do |locator = nil, **options, &optional_filter_block|\n        Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block)\n      end\n    end\n\n    # @!method have_element(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for elements.\n    #\n    #   @see Capybara::Node::Matchers#has_element?\n\n    # @!method have_link(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for links.\n    #\n    #   @see Capybara::Node::Matchers#has_link?\n\n    # @!method have_button(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for buttons.\n    #\n    #   @see Capybara::Node::Matchers#has_button?\n\n    # @!method have_field(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for form fields.\n    #\n    #   @see Capybara::Node::Matchers#has_field?\n\n    # @!method have_select(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for select elements.\n    #\n    #   @see Capybara::Node::Matchers#has_select?\n\n    # @!method have_table(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for table elements.\n    #\n    #   @see Capybara::Node::Matchers#has_table?\n\n    %i[checked unchecked].each do |state|\n      define_method \"have_#{state}_field\" do |locator = nil, **options, &optional_filter_block|\n        Matchers::HaveSelector.new(:field, locator, **options.merge(state => true), &optional_filter_block)\n      end\n    end\n\n    # @!method have_checked_field(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for checked fields.\n    #\n    #   @see Capybara::Node::Matchers#has_checked_field?\n\n    # @!method have_unchecked_field(locator = nil, **options, &optional_filter_block)\n    #   RSpec matcher for unchecked fields.\n    #\n    #   @see Capybara::Node::Matchers#has_unchecked_field?\n\n    # RSpec matcher for text content.\n    #\n    # @see Capybara::Node::Matchers#assert_text\n    def have_text(text_or_type, *args, **options)\n      Matchers::HaveText.new(text_or_type, *args, **options)\n    end\n    alias_method :have_content, :have_text\n\n    def have_title(title, **options)\n      Matchers::HaveTitle.new(title, **options)\n    end\n\n    # RSpec matcher for the current path.\n    #\n    # @see Capybara::SessionMatchers#assert_current_path\n    def have_current_path(path, **options, &optional_filter_block)\n      Matchers::HaveCurrentPath.new(path, **options, &optional_filter_block)\n    end\n\n    # RSpec matcher for element style.\n    #\n    # @see Capybara::Node::Matchers#matches_style?\n    def match_style(styles = nil, **options)\n      styles, options = options, {} if styles.nil?\n      Matchers::MatchStyle.new(styles, **options)\n    end\n\n    ##\n    # @deprecated\n    #\n    def have_style(styles = nil, **options)\n      Capybara::Helpers.warn \"DEPRECATED: have_style is deprecated, please use match_style : #{Capybara::Helpers.filter_backtrace(caller)}\"\n      match_style(styles, **options)\n    end\n\n    %w[selector css xpath text title current_path link button\n       field checked_field unchecked_field select table\n       sibling ancestor element].each do |matcher_type|\n      define_method \"have_no_#{matcher_type}\" do |*args, **kw_args, &optional_filter_block|\n        Matchers::NegatedMatcher.new(send(\"have_#{matcher_type}\", *args, **kw_args, &optional_filter_block))\n      end\n    end\n    alias_method :have_no_content, :have_no_text\n\n    %w[selector css xpath].each do |matcher_type|\n      define_method \"not_match_#{matcher_type}\" do |*args, **kw_args, &optional_filter_block|\n        Matchers::NegatedMatcher.new(send(\"match_#{matcher_type}\", *args, **kw_args, &optional_filter_block))\n      end\n    end\n\n    # RSpec matcher for whether sibling element(s) matching a given selector exist.\n    #\n    # @see Capybara::Node::Matchers#assert_sibling\n    def have_sibling(...)\n      Matchers::HaveSibling.new(...)\n    end\n\n    # RSpec matcher for whether ancestor element(s) matching a given selector exist.\n    #\n    # @see Capybara::Node::Matchers#assert_ancestor\n    def have_ancestor(...)\n      Matchers::HaveAncestor.new(...)\n    end\n\n    ##\n    # Wait for window to become closed.\n    #\n    # @example\n    #   expect(window).to become_closed(wait: 0.8)\n    #\n    # @option options [Numeric] :wait   Maximum wait time. Defaults to {Capybara.configure default_max_wait_time}\n    def become_closed(**options)\n      Matchers::BecomeClosed.new(options)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/rspec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rspec/core'\nrequire 'capybara/dsl'\nrequire 'capybara/rspec/matchers'\nrequire 'capybara/rspec/features'\nrequire 'capybara/rspec/matcher_proxies'\n\nRSpec.configure do |config|\n  config.include Capybara::DSL, type: :feature\n  config.include Capybara::RSpecMatchers, type: :feature\n  config.include Capybara::DSL, type: :system\n  config.include Capybara::RSpecMatchers, type: :system\n  config.include Capybara::RSpecMatchers, type: :view\n\n  # The before and after blocks must run instantaneously, because Capybara\n  # might not actually be used in all examples where it's included.\n  config.after do\n    if self.class.include?(Capybara::DSL)\n      Capybara.reset_sessions!\n      Capybara.use_default_driver\n    end\n  end\n\n  config.before do |example|\n    if self.class.include?(Capybara::DSL)\n      Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]\n      Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/builders/css_builder.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'xpath'\n\nmodule Capybara\n  class Selector\n    # @api private\n    class CSSBuilder\n      def initialize(expression)\n        @expression = expression || ''\n      end\n\n      attr_reader :expression\n\n      def add_attribute_conditions(**attributes)\n        @expression = attributes.inject(expression) do |css, (name, value)|\n          conditions = if name == :class\n            class_conditions(value)\n          elsif value.is_a? Regexp\n            regexp_conditions(name, value)\n          else\n            [attribute_conditions(name => value)]\n          end\n\n          ::Capybara::Selector::CSS.split(css).map do |sel|\n            next sel if conditions.empty?\n\n            conditions.map { |cond| sel + cond }.join(', ')\n          end.join(', ')\n        end\n      end\n\n    private\n\n      def regexp_conditions(name, value)\n        Selector::RegexpDisassembler.new(value).alternated_substrings.map do |strs|\n          strs.map do |str|\n            \"[#{name}*='#{str}'#{' i' if value.casefold?}]\"\n          end.join\n        end\n      end\n\n      def attribute_conditions(attributes)\n        attributes.map do |attribute, value|\n          case value\n          when XPath::Expression\n            raise ArgumentError, \"XPath expressions are not supported for the :#{attribute} filter with CSS based selectors\"\n          when Regexp\n            Selector::RegexpDisassembler.new(value).substrings.map do |str|\n              \"[#{attribute}*='#{str}'#{' i' if value.casefold?}]\"\n            end.join\n          when true\n            \"[#{attribute}]\"\n          when false\n            ':not([attribute])'\n          else\n            if attribute == :id\n              \"##{::Capybara::Selector::CSS.escape(value)}\"\n            else\n              \"[#{attribute}='#{value}']\"\n            end\n          end\n        end.join\n      end\n\n      def class_conditions(classes)\n        case classes\n        when XPath::Expression\n          raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'\n        when Regexp\n          Selector::RegexpDisassembler.new(classes).alternated_substrings.map do |strs|\n            strs.map do |str|\n              \"[class*='#{str}'#{' i' if classes.casefold?}]\"\n            end.join\n          end\n        else\n          cls = Array(classes).reject { |c| c.is_a? Regexp }.group_by { |cl| cl.match?(/^!(?!!!)/) }\n          [(cls[false].to_a.map { |cl| \".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}\" } +\n          cls[true].to_a.map { |cl| \":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..))})\" }).join]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/builders/xpath_builder.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'xpath'\n\nmodule Capybara\n  class Selector\n    # @api private\n    class XPathBuilder\n      def initialize(expression)\n        @expression = expression || ''\n      end\n\n      attr_reader :expression\n\n      def add_attribute_conditions(**conditions)\n        @expression = conditions.inject(expression) do |xp, (name, value)|\n          conditions = name == :class ? class_conditions(value) : attribute_conditions(name => value)\n          return xp if conditions.nil?\n\n          if xp.is_a? XPath::Expression\n            xp[conditions]\n          else\n            \"(#{xp})[#{conditions}]\"\n          end\n        end\n      end\n\n    private\n\n      def attribute_conditions(attributes)\n        attributes.map do |attribute, value|\n          case value\n          when XPath::Expression\n            XPath.attr(attribute)[value]\n          when Regexp\n            XPath.attr(attribute)[regexp_to_xpath_conditions(value)]\n          when true\n            XPath.attr(attribute)\n          when false, nil\n            !XPath.attr(attribute)\n          else\n            XPath.attr(attribute) == value.to_s\n          end\n        end.reduce(:&)\n      end\n\n      def class_conditions(classes)\n        case classes\n        when XPath::Expression, Regexp\n          attribute_conditions(class: classes)\n        else\n          Array(classes).reject { |c| c.is_a? Regexp }.map do |klass|\n            if klass.match?(/^!(?!!!)/)\n              !XPath.attr(:class).contains_word(klass.slice(1..))\n            else\n              XPath.attr(:class).contains_word(klass.sub(/^!!/, ''))\n            end\n          end.reduce(:&)\n        end\n      end\n\n      def regexp_to_xpath_conditions(regexp)\n        condition = XPath.current\n        condition = condition.uppercase if regexp.casefold?\n        Selector::RegexpDisassembler.new(regexp).alternated_substrings.map do |strs|\n          strs.map { |str| condition.contains(str) }.reduce(:&)\n        end.reduce(:|)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/css.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/selector'\n\nmodule Capybara\n  class Selector\n    class CSS\n      def self.escape(str)\n        value = str.dup\n        out = +''\n        out << value.slice!(0...1) if value.match?(/^[-_]/)\n        out << (value[0].match?(NMSTART) ? value.slice!(0...1) : escape_char(value.slice!(0...1)))\n        out << value.gsub(/[^a-zA-Z0-9_-]/) { |char| escape_char char }\n        out\n      end\n\n      def self.escape_char(char)\n        char.match?(%r{[ -/:-~]}) ? \"\\\\#{char}\" : format('\\\\%06<hex>x', hex: char.ord)\n      end\n\n      def self.split(css)\n        Splitter.new.split(css)\n      end\n\n      S = '\\u{80}-\\u{D7FF}\\u{E000}-\\u{FFFD}\\u{10000}-\\u{10FFFF}'\n      H = /[0-9a-fA-F]/\n      UNICODE  = /\\\\#{H}{1,6}[ \\t\\r\\n\\f]?/\n      NONASCII = /[#{S}]/\n      ESCAPE   = /#{UNICODE}|\\\\[ -~#{S}]/\n      NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/\n\n      class Splitter\n        def split(css)\n          selectors = []\n          StringIO.open(css.to_s) do |str|\n            selector = +''\n            while (char = str.getc)\n              case char\n              when '['\n                selector << parse_square(str)\n              when '('\n                selector << parse_paren(str)\n              when '\"', \"'\"\n                selector << parse_string(char, str)\n              when '\\\\'\n                selector << (char + str.getc)\n              when ','\n                selectors << selector.strip\n                selector.clear\n              else\n                selector << char\n              end\n            end\n            selectors << selector.strip\n          end\n          selectors\n        end\n\n      private\n\n        def parse_square(strio)\n          parse_block('[', ']', strio)\n        end\n\n        def parse_paren(strio)\n          parse_block('(', ')', strio)\n        end\n\n        def parse_block(start, final, strio)\n          block = start\n          while (char = strio.getc)\n            case char\n            when final\n              return block + char\n            when '\\\\'\n              block += char + strio.getc\n            when '\"', \"'\"\n              block += parse_string(char, strio)\n            else\n              block += char\n            end\n          end\n          raise ArgumentError, \"Invalid CSS Selector - Block end '#{final}' not found\"\n        end\n\n        def parse_string(quote, strio)\n          string = quote\n          while (char = strio.getc)\n            string += char\n            case char\n            when quote\n              return string\n            when '\\\\'\n              string += strio.getc\n            end\n          end\n          raise ArgumentError, 'Invalid CSS Selector - string end not found'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/button.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:button, locator_type: [String, Symbol]) do\n  xpath(:value, :title, :type, :name) do |locator, **options|\n    input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]\n    btn_xpath = XPath.descendant(:button)\n    aria_btn_xpath = XPath.descendant[XPath.attr(:role).equals('button')]\n    image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image']\n\n    unless locator.nil?\n      locator = locator.to_s\n      locator_matchers = combine_locators(locator, config: self)\n      btn_matchers = locator_matchers |\n                     XPath.string.n.is(locator) |\n                     XPath.descendant(:img)[XPath.attr(:alt).is(locator)]\n\n      label_contains_xpath = locate_label(locator).descendant[labellable_elements]\n      input_btn_xpath = input_btn_xpath[locator_matchers]\n      btn_xpath = btn_xpath[btn_matchers]\n      aria_btn_xpath = aria_btn_xpath[btn_matchers]\n\n      alt_matches = XPath.attr(:alt).is(locator)\n      alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label\n      image_btn_xpath = image_btn_xpath[alt_matches]\n    end\n\n    btn_xpaths = [input_btn_xpath, btn_xpath, image_btn_xpath, label_contains_xpath].compact\n    btn_xpaths << aria_btn_xpath if enable_aria_role\n\n    %i[value title type].inject(btn_xpaths.inject(&:union)) do |memo, ef|\n      memo.where(find_by_attr(ef, options[ef]))\n    end\n  end\n\n  node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }\n  expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }\n\n  node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }\n  expression_filter(:name) do |xpath, val|\n    builder(xpath).add_attribute_conditions(name: val)\n  end\n\n  describe_expression_filters do |disabled: nil, **options|\n    desc = +''\n    desc << ' that is not disabled' if disabled == false\n    desc << describe_all_expression_filters(**options)\n  end\n\n  describe_node_filters do |disabled: nil, **|\n    ' that is disabled' if disabled == true\n  end\n\n  def combine_locators(locator, config:)\n    [\n      XPath.attr(:id).equals(locator),\n      XPath.attr(:name).equals(locator),\n      XPath.attr(:value).is(locator),\n      XPath.attr(:title).is(locator),\n      (XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)),\n      (XPath.attr(:'aria-label').is(locator) if config.enable_aria_label),\n      (XPath.attr(config.test_id) == locator if config.test_id)\n    ].compact.inject(&:|)\n  end\n\n  def labellable_elements\n    (XPath.self(:input) & XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')) | XPath.self(:button)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/checkbox.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:checkbox, locator_type: [String, Symbol]) do\n  xpath do |locator, allow_self: nil, **options|\n    xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[\n      XPath.attr(:type) == 'checkbox'\n    ]\n    locate_field(xpath, locator, **options)\n  end\n\n  filter_set(:_field, %i[checked unchecked disabled name])\n\n  node_filter(%i[option with]) do |node, value|\n    val = node.value\n    (value.is_a?(Regexp) ? value.match?(val) : val == value.to_s).tap do |res|\n      add_error(\"Expected value to be #{value.inspect} but it was #{val.inspect}\") unless res\n    end\n  end\n\n  describe_node_filters do |option: nil, with: nil, **|\n    desc = +''\n    desc << \" with value #{option.inspect}\" if option\n    desc << \" with value #{with.inspect}\" if with\n    desc\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/css.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:css, locator_type: [String, Symbol], raw_locator: true) do\n  css do |css|\n    if css.is_a? Symbol\n      Capybara::Helpers.warn \"DEPRECATED: Passing a symbol (#{css.inspect}) as the CSS locator is deprecated - please pass a string instead : #{Capybara::Helpers.filter_backtrace(caller)}\"\n    end\n    css\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/datalist_input.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:datalist_input, locator_type: [String, Symbol]) do\n  label 'input box with datalist completion'\n\n  xpath do |locator, **options|\n    xpath = XPath.descendant(:input)[XPath.attr(:list)]\n    locate_field(xpath, locator, **options)\n  end\n\n  filter_set(:_field, %i[disabled name placeholder])\n\n  node_filter(:options) do |node, options|\n    actual = node.find(\"//datalist[@id=#{node[:list]}]\", visible: :all).all(:datalist_option, wait: false).map(&:value)\n    (options.sort == actual.sort).tap do |res|\n      add_error(\"Expected #{options.inspect} options found #{actual.inspect}\") unless res\n    end\n  end\n\n  expression_filter(:with_options) do |expr, options|\n    options.inject(expr) do |xpath, option|\n      xpath.where(XPath.attr(:list) == XPath.anywhere(:datalist)[expression_for(:datalist_option, option)].attr(:id))\n    end\n  end\n\n  describe_expression_filters do |with_options: nil, **|\n    desc = +''\n    desc << \" with at least options #{with_options.inspect}\" if with_options\n    desc\n  end\n\n  describe_node_filters do |options: nil, **|\n    \" with options #{options.inspect}\" if options\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/datalist_option.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:datalist_option, locator_type: [String, Symbol]) do\n  label 'datalist option'\n  visible(:all)\n\n  xpath do |locator|\n    xpath = XPath.descendant(:option)\n    xpath = xpath[XPath.string.n.is(locator.to_s) | (XPath.attr(:value) == locator.to_s)] unless locator.nil?\n    xpath\n  end\n\n  node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }\n  expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }\n\n  describe_expression_filters do |disabled: nil, **options|\n    desc = +''\n    desc << ' that is not disabled' if disabled == false\n    desc << describe_all_expression_filters(**options)\n  end\n\n  describe_node_filters do |**options|\n    ' that is disabled' if options[:disabled]\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/element.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:element, locator_type: [String, Symbol]) do\n  xpath do |locator, **|\n    XPath.descendant.where(locator ? XPath.local_name == locator.to_s : nil)\n  end\n\n  expression_filter(:attributes, matcher: /.+/) do |xpath, name, val|\n    builder(xpath).add_attribute_conditions(name => val)\n  end\n\n  node_filter(:attributes, matcher: /.+/) do |node, name, val|\n    next true unless val.is_a?(Regexp)\n\n    (val.match? node[name]).tap do |res|\n      add_error(\"Expected #{name} to match #{val.inspect} but it was #{node[name]}\") unless res\n    end\n  end\n\n  describe_expression_filters do |**options|\n    boolean_values = [true, false]\n    booleans, values = options.partition { |_k, v| boolean_values.include? v }.map(&:to_h)\n    desc = describe_all_expression_filters(**values)\n    desc + booleans.map do |k, v|\n      v ? \" with #{k} attribute\" : \"without #{k} attribute\"\n    end.join\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/field.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:field, locator_type: [String, Symbol]) do\n  visible { |options| :hidden if options[:type].to_s == 'hidden' }\n\n  xpath do |locator, **options|\n    invalid_types = %w[submit image]\n    invalid_types << 'hidden' unless options[:type].to_s == 'hidden'\n    xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of(*invalid_types)]\n    locate_field(xpath, locator, **options)\n  end\n\n  expression_filter(:type) do |expr, type|\n    type = type.to_s\n    if %w[textarea select].include?(type)\n      expr.self(type.to_sym)\n    else\n      expr[XPath.attr(:type) == type]\n    end\n  end\n\n  filter_set(:_field) # checked/unchecked/disabled/multiple/name/placeholder\n\n  node_filter(:readonly, :boolean) { |node, value| !(value ^ node.readonly?) }\n\n  node_filter(:with) do |node, with|\n    val = node.value\n    (with.is_a?(Regexp) ? with.match?(val) : val == with.to_s).tap do |res|\n      add_error(\"Expected value to be #{with.inspect} but was #{val.inspect}\") unless res\n    end\n  end\n\n  describe_expression_filters do |type: nil, **|\n    \" of type #{type.inspect}\" if type\n  end\n\n  describe_node_filters do |**options|\n    \" with value #{options[:with].to_s.inspect}\" if options.key?(:with)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/fieldset.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:fieldset, locator_type: [String, Symbol]) do\n  xpath do |locator, legend: nil, **|\n    locator_matchers = (XPath.attr(:id) == locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)]\n    locator_matchers |= XPath.attr(test_id) == locator.to_s if test_id\n    xpath = XPath.descendant(:fieldset)[locator && locator_matchers]\n    xpath = xpath[XPath.child(:legend)[XPath.string.n.is(legend)]] if legend\n    xpath\n  end\n\n  node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }\n  expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/file_field.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:file_field, locator_type: [String, Symbol]) do\n  label 'file field'\n  xpath do |locator, allow_self: nil, **options|\n    xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[\n      XPath.attr(:type) == 'file'\n    ]\n    locate_field(xpath, locator, **options)\n  end\n\n  filter_set(:_field, %i[disabled multiple name])\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/fillable_field.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:fillable_field, locator_type: [String, Symbol]) do\n  label 'field'\n  xpath do |locator, allow_self: nil, **options|\n    xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input, :textarea)[\n      !XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')\n    ]\n    locate_field(xpath, locator, **options)\n  end\n\n  expression_filter(:type) do |expr, type|\n    type = type.to_s\n    if type == 'textarea'\n      expr.self(type.to_sym)\n    else\n      expr[XPath.attr(:type) == type]\n    end\n  end\n\n  filter_set(:_field, %i[disabled multiple name placeholder valid validation_message])\n\n  node_filter(:with) do |node, with|\n    val = node.value\n    (with.is_a?(Regexp) ? with.match?(val) : val == with.to_s).tap do |res|\n      add_error(\"Expected value to be #{with.inspect} but was #{val.inspect}\") unless res\n    end\n  end\n\n  describe_node_filters do |**options|\n    \" with value #{options[:with].to_s.inspect}\" if options.key?(:with)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/frame.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:frame, locator_type: [String, Symbol]) do\n  xpath do |locator, name: nil, **|\n    xpath = XPath.descendant(:iframe).union(XPath.descendant(:frame))\n    unless locator.nil?\n      locator_matchers = (XPath.attr(:id) == locator.to_s) | (XPath.attr(:name) == locator.to_s)\n      locator_matchers |= XPath.attr(test_id) == locator.to_s if test_id\n      xpath = xpath[locator_matchers]\n    end\n    xpath[find_by_attr(:name, name)]\n  end\n\n  describe_expression_filters do |name: nil, **|\n    \" with name #{name}\" if name\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/id.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:id, locator_type: [String, Symbol, Regexp]) do\n  xpath { |id| builder(XPath.descendant).add_attribute_conditions(id: id) }\n  locator_filter { |node, id| id.is_a?(Regexp) ? id.match?(node[:id]) : true }\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/label.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:label, locator_type: [String, Symbol]) do\n  label 'label'\n  xpath(:for) do |locator, **options|\n    xpath = XPath.descendant(:label)\n    unless locator.nil?\n      locator_matchers = XPath.string.n.is(locator.to_s) | (XPath.attr(:id) == locator.to_s)\n      locator_matchers |= XPath.attr(test_id) == locator.to_s if test_id\n      xpath = xpath[locator_matchers]\n    end\n    if options.key?(:for)\n      for_option = options[:for]\n      for_option = for_option[:id] if for_option.is_a?(Capybara::Node::Element)\n      if for_option && (for_option != '')\n        with_attr = builder(XPath.self).add_attribute_conditions(for: for_option)\n        wrapped = !XPath.attr(:for) &\n                  builder(XPath.self.descendant(*labelable_elements)).add_attribute_conditions(id: for_option)\n        xpath = xpath[with_attr | wrapped]\n      end\n    end\n    xpath\n  end\n\n  node_filter(:for) do |node, field_or_value|\n    case field_or_value\n    when Capybara::Node::Element\n      if (for_val = node[:for])\n        field_or_value[:id] == for_val\n      else\n        field_or_value.find_xpath('./ancestor::label[1]').include? node.base\n      end\n    when Regexp\n      if (for_val = node[:for])\n        field_or_value.match? for_val\n      else\n        node.find_xpath(XPath.descendant(*labelable_elements).to_s)\n            .any? { |n| field_or_value.match? n[:id] }\n      end\n    else\n      # Non element/regexp values were handled through the expression filter\n      true\n    end\n  end\n\n  describe_expression_filters do |**options|\n    next unless options.key?(:for) && !options[:for].is_a?(Capybara::Node::Element)\n\n    if options[:for].is_a? Regexp\n      \" for element with id matching #{options[:for].inspect}\"\n    else\n      \" for element with id of \\\"#{options[:for]}\\\"\"\n    end\n  end\n  describe_node_filters do |**options|\n    \" for element #{options[:for]}\" if options[:for].is_a?(Capybara::Node::Element)\n  end\n\n  def labelable_elements\n    %i[button input keygen meter output progress select textarea]\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/link.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:link, locator_type: [String, Symbol]) do\n  xpath do |locator, href: true, alt: nil, title: nil, target: nil, **|\n    xpath = XPath.descendant(:a)\n    xpath = builder(xpath).add_attribute_conditions(href: href) unless href == false\n\n    if enable_aria_role\n      role_path = XPath.descendant[XPath.attr(:role).equals('link')]\n      role_path = builder(role_path).add_attribute_conditions(href: href) unless [true, false].include? href\n\n      xpath += role_path\n    end\n\n    unless locator.nil?\n      locator = locator.to_s\n      matchers = [XPath.attr(:id) == locator,\n                  XPath.string.n.is(locator),\n                  XPath.attr(:title).is(locator),\n                  XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]\n      matchers << XPath.attr(:'aria-label').is(locator) if enable_aria_label\n      matchers << XPath.attr(test_id).equals(locator) if test_id\n      xpath = xpath[matchers.reduce(:|)]\n    end\n\n    xpath = xpath[find_by_attr(:title, title)]\n    xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt\n    xpath = xpath[find_by_attr(:target, target)] if target\n\n    xpath\n  end\n\n  node_filter(:href) do |node, href|\n    # If not a Regexp it's been handled in the main XPath\n    (href.is_a?(Regexp) ? node[:href].match?(href) : true).tap do |res|\n      add_error \"Expected href to match #{href.inspect} but it was #{node[:href].inspect}\" unless res\n    end\n  end\n\n  expression_filter(:download, valid_values: [true, false, String]) do |expr, download|\n    builder(expr).add_attribute_conditions(download: download)\n  end\n\n  describe_expression_filters do |download: nil, **options|\n    desc = +''\n    if (href = options[:href])\n      desc << \" with href #{'matching ' if href.is_a? Regexp}#{href.inspect}\"\n    elsif options.key?(:href) && href != false # is nil specified?\n      desc << ' with no href attribute'\n    end\n    desc << \" with download attribute#{\" #{download}\" if download.is_a? String}\" if download\n    desc << ' without download attribute' if download == false\n    desc\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/link_or_button.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:link_or_button, locator_type: [String, Symbol]) do\n  label 'link or button'\n  xpath do |locator, **options|\n    %i[link button].map do |selector|\n      expression_for(selector, locator, **options)\n    end.reduce(:union)\n  end\n\n  node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }\n\n  describe_node_filters do |disabled: nil, **|\n    ' that is disabled' if disabled == true\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/option.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:option, locator_type: [String, Symbol, Integer]) do\n  xpath do |locator|\n    xpath = XPath.descendant(:option)\n    xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?\n    xpath\n  end\n\n  node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }\n  expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }\n\n  node_filter(:selected, :boolean) { |node, value| !(value ^ node.selected?) }\n\n  describe_expression_filters do |disabled: nil, **options|\n    desc = +''\n    desc << ' that is not disabled' if disabled == false\n    (expression_filters.keys & options.keys).inject(desc) { |memo, ef| memo << \" with #{ef} #{options[ef]}\" }\n  end\n\n  describe_node_filters do |**options|\n    desc = +''\n    desc << ' that is disabled' if options[:disabled]\n    desc << \" that is#{' not' unless options[:selected]} selected\" if options.key?(:selected)\n    desc\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/radio_button.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:radio_button, locator_type: [String, Symbol]) do\n  label 'radio button'\n  xpath do |locator, allow_self: nil, **options|\n    xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[\n      XPath.attr(:type) == 'radio'\n    ]\n    locate_field(xpath, locator, **options)\n  end\n\n  filter_set(:_field, %i[checked unchecked disabled name])\n\n  node_filter(%i[option with]) do |node, value|\n    val = node.value\n    (value.is_a?(Regexp) ? value.match?(val) : val == value.to_s).tap do |res|\n      add_error(\"Expected value to be #{value.inspect} but it was #{val.inspect}\") unless res\n    end\n  end\n\n  describe_node_filters do |option: nil, with: nil, **|\n    desc = +''\n    desc << \" with value #{option.inspect}\" if option\n    desc << \" with value #{with.inspect}\" if with\n    desc\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/select.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:select, locator_type: [String, Symbol]) do\n  label 'select box'\n\n  xpath do |locator, **options|\n    xpath = XPath.descendant(:select)\n    locate_field(xpath, locator, **options)\n  end\n\n  filter_set(:_field, %i[disabled multiple name placeholder])\n\n  node_filter(:options) do |node, options|\n    actual = options_text(node)\n    (options.sort == actual.sort).tap do |res|\n      add_error(\"Expected options #{options.inspect} found #{actual.inspect}\") unless res\n    end\n  end\n\n  node_filter(:enabled_options) do |node, options|\n    actual = options_text(node) { |o| !o.disabled? }\n    (options.sort == actual.sort).tap do |res|\n      add_error(\"Expected enabled options #{options.inspect} found #{actual.inspect}\") unless res\n    end\n  end\n\n  node_filter(:disabled_options) do |node, options|\n    actual = options_text(node, &:disabled?)\n    (options.sort == actual.sort).tap do |res|\n      add_error(\"Expected disabled options #{options.inspect} found #{actual.inspect}\") unless res\n    end\n  end\n\n  expression_filter(:with_options) do |expr, options|\n    options.inject(expr) do |xpath, option|\n      xpath.where(expression_for(:option, option))\n    end\n  end\n\n  node_filter(:selected) do |node, selected|\n    actual = options_text(node, visible: false, &:selected?)\n    (Array(selected).sort == actual.sort).tap do |res|\n      add_error(\"Expected #{selected.inspect} to be selected found #{actual.inspect}\") unless res\n    end\n  end\n\n  node_filter(:with_selected) do |node, selected|\n    actual = options_text(node, visible: false, &:selected?)\n    (Array(selected) - actual).empty?.tap do |res|\n      add_error(\"Expected at least #{selected.inspect} to be selected found #{actual.inspect}\") unless res\n    end\n  end\n\n  describe_expression_filters do |with_options: nil, **|\n    desc = +''\n    desc << \" with at least options #{with_options.inspect}\" if with_options\n    desc\n  end\n\n  describe_node_filters do |\n    options: nil, disabled_options: nil, enabled_options: nil,\n    selected: nil, with_selected: nil,\n    disabled: nil, **|\n    desc = +''\n    desc << \" with options #{options.inspect}\" if options\n    desc << \" with disabled options #{disabled_options.inspect}}\" if disabled_options\n    desc << \" with enabled options #{enabled_options.inspect}\" if enabled_options\n    desc << \" with #{selected.inspect} selected\" if selected\n    desc << \" with at least #{with_selected.inspect} selected\" if with_selected\n    desc << ' which is disabled' if disabled\n    desc\n  end\n\n  def options_text(node, **opts, &filter_block)\n    opts[:wait] = false\n    opts[:visible] = false unless node.visible?\n    node.all(:xpath, './/option', **opts, &filter_block).map do |o|\n      o.text((:all if opts[:visible] == false))\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/table.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:table, locator_type: [String, Symbol]) do\n  xpath do |locator, caption: nil, **|\n    xpath = XPath.descendant(:table)\n    unless locator.nil?\n      locator_matchers = (XPath.attr(:id) == locator.to_s) | XPath.descendant(:caption).is(locator.to_s)\n      locator_matchers |= XPath.attr(test_id) == locator.to_s if test_id\n      xpath = xpath[locator_matchers]\n    end\n    xpath = xpath[XPath.descendant(:caption) == caption] if caption\n    xpath\n  end\n\n  expression_filter(:with_cols, valid_values: [Array]) do |xpath, cols|\n    col_conditions = cols.map do |col|\n      if col.is_a? Hash\n        col.reduce(nil) do |xp, (header, cell_str)|\n          header = XPath.descendant(:th)[XPath.string.n.is(header)]\n          td = XPath.descendant(:tr)[header].descendant(:td)\n          cell_condition = XPath.string.n.is(cell_str)\n          if xp\n            prev_cell = XPath.ancestor(:table)[1].join(xp)\n            cell_condition &= (prev_cell & prev_col_position?(prev_cell))\n          end\n          td[cell_condition]\n        end\n      else\n        cells_xp = col.reduce(nil) do |prev_cell, cell_str|\n          cell_condition = XPath.string.n.is(cell_str)\n\n          if prev_cell\n            prev_cell = XPath.ancestor(:tr)[1].preceding_sibling(:tr).join(prev_cell)\n            cell_condition &= (prev_cell & prev_col_position?(prev_cell))\n          end\n\n          XPath.descendant(:td)[cell_condition]\n        end\n        XPath.descendant(:tr).join(cells_xp)\n      end\n    end.reduce(:&)\n    xpath[col_conditions]\n  end\n\n  expression_filter(:cols, valid_values: [Array]) do |xpath, cols|\n    raise ArgumentError, ':cols must be an Array of Arrays' unless cols.all?(Array)\n\n    rows = cols.transpose\n    col_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)\n    xpath[match_row_count(rows.size)][col_conditions]\n  end\n\n  expression_filter(:with_rows, valid_values: [Array]) do |xpath, rows|\n    rows_conditions = rows.map { |row| match_row(row) }.reduce(:&)\n    xpath[rows_conditions]\n  end\n\n  expression_filter(:rows, valid_values: [Array]) do |xpath, rows|\n    rows_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)\n    xpath[match_row_count(rows.size)][rows_conditions]\n  end\n\n  describe_expression_filters do |caption: nil, **|\n    \" with caption \\\"#{caption}\\\"\" if caption\n  end\n\n  def prev_col_position?(cell)\n    XPath.position.equals(cell_position(cell))\n  end\n\n  def cell_position(cell)\n    cell.preceding_sibling(:td).count.plus(1)\n  end\n\n  def match_row(row, match_size: false)\n    xp = XPath.descendant(:tr)[\n      if row.is_a? Hash\n        row_match_cells_to_headers(row)\n      else\n        XPath.descendant(:td)[row_match_ordered_cells(row)]\n      end\n    ]\n    xp = xp[XPath.descendant(:td).count.equals(row.size)] if match_size\n    xp\n  end\n\n  def match_row_count(size)\n    XPath.descendant(:tbody).descendant(:tr).count.equals(size) |\n      (XPath.descendant(:tr).count.equals(size) & ~XPath.descendant(:tbody))\n  end\n\n  def row_match_cells_to_headers(row)\n    row.map do |header, cell|\n      header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]\n      XPath.descendant(:td)[\n        XPath.string.n.is(cell) & header_xp.boolean & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))\n      ]\n    end.reduce(:&)\n  end\n\n  def row_match_ordered_cells(row)\n    row_conditions = row.map do |cell|\n      XPath.self(:td)[XPath.string.n.is(cell)]\n    end\n    row_conditions.reverse.reduce do |cond, cell|\n      cell[XPath.following_sibling[cond]]\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/table_row.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:table_row, locator_type: [Array, Hash]) do\n  xpath do |locator|\n    xpath = XPath.descendant(:tr)\n    if locator.is_a? Hash\n      locator.reduce(xpath) do |xp, (header, cell)|\n        header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]\n        cell_xp = XPath.descendant(:td)[\n          XPath.string.n.is(cell) & header_xp.boolean & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))\n        ]\n        xp.where(cell_xp)\n      end\n    elsif locator.is_a? Array\n      initial_td = XPath.descendant(:td)[XPath.string.n.is(locator.shift)]\n      tds = locator.reverse.map { |cell| XPath.following_sibling(:td)[XPath.string.n.is(cell)] }\n                   .reduce { |xp, cell| cell.where(xp) }\n      xpath[initial_td[tds]]\n    else\n      xpath\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition/xpath.rb",
    "content": "# frozen_string_literal: true\n\nCapybara.add_selector(:xpath, locator_type: [:to_xpath, String], raw_locator: true) do\n  xpath { |xpath| xpath }\nend\n"
  },
  {
    "path": "lib/capybara/selector/definition.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filter_set'\nrequire 'capybara/selector/css'\nrequire 'capybara/selector/regexp_disassembler'\nrequire 'capybara/selector/builders/xpath_builder'\nrequire 'capybara/selector/builders/css_builder'\n\nmodule Capybara\n  class Selector\n    class Definition\n      attr_reader :name, :expressions\n\n      extend Forwardable\n\n      def initialize(name, locator_type: nil, raw_locator: false, supports_exact: nil, &block)\n        @name = name\n        @filter_set = Capybara::Selector::FilterSet.add(name)\n        @match = nil\n        @label = nil\n        @failure_message = nil\n        @expressions = {}\n        @expression_filters = {}\n        @locator_filter = nil\n        @default_visibility = nil\n        @locator_type = locator_type\n        @raw_locator = raw_locator\n        @supports_exact = supports_exact\n        instance_eval(&block)\n      end\n\n      def custom_filters\n        warn \"Deprecated: Selector#custom_filters is not valid when same named expression and node filter exist - don't use\"\n        node_filters.merge(expression_filters).freeze\n      end\n\n      def node_filters\n        @filter_set.node_filters\n      end\n\n      def expression_filters\n        @filter_set.expression_filters\n      end\n\n      ##\n      #\n      # Define a selector by an xpath expression\n      #\n      # @overload xpath(*expression_filters, &block)\n      #   @param [Array<Symbol>] expression_filters ([])  Names of filters that are implemented via this expression, if not specified the names of any keyword parameters in the block will be used\n      #   @yield [locator, options]                       The block to use to generate the XPath expression\n      #   @yieldparam [String] locator                    The locator string passed to the query\n      #   @yieldparam [Hash] options                      The options hash passed to the query\n      #   @yieldreturn [#to_xpath, #to_s]                 An object that can produce an xpath expression\n      #\n      # @overload xpath()\n      # @return [#call]                             The block that will be called to generate the XPath expression\n      #\n      def xpath(*allowed_filters, &block)\n        expression(:xpath, allowed_filters, &block)\n      end\n\n      ##\n      #\n      # Define a selector by a CSS selector\n      #\n      # @overload css(*expression_filters, &block)\n      #   @param [Array<Symbol>] expression_filters ([])  Names of filters that can be implemented via this CSS selector\n      #   @yield [locator, options]                   The block to use to generate the CSS selector\n      #   @yieldparam [String] locator               The locator string passed to the query\n      #   @yieldparam [Hash] options                 The options hash passed to the query\n      #   @yieldreturn [#to_s]                        An object that can produce a CSS selector\n      #\n      # @overload css()\n      # @return [#call]                             The block that will be called to generate the CSS selector\n      #\n      def css(*allowed_filters, &block)\n        expression(:css, allowed_filters, &block)\n      end\n\n      ##\n      #\n      # Automatic selector detection\n      #\n      # @yield [locator]                   This block takes the passed in locator string and returns whether or not it matches the selector\n      # @yieldparam [String], locator      The locator string used to determine if it matches the selector\n      # @yieldreturn [Boolean]             Whether this selector matches the locator string\n      # @return [#call]                    The block that will be used to detect selector match\n      #\n      def match(&block)\n        @match = block if block\n        @match\n      end\n\n      ##\n      #\n      # Set/get a descriptive label for the selector\n      #\n      # @overload label(label)\n      #   @param [String] label            A descriptive label for this selector - used in error messages\n      # @overload label()\n      # @return [String]                 The currently set label\n      #\n      def label(label = nil)\n        @label = label if label\n        @label\n      end\n\n      ##\n      #\n      # Description of the selector\n      #\n      # @!method description(options)\n      #   @param [Hash] options            The options of the query used to generate the description\n      #   @return [String]                 Description of the selector when used with the options passed\n      def_delegator :@filter_set, :description\n\n      ##\n      #\n      #  Should this selector be used for the passed in locator\n      #\n      #  This is used by the automatic selector selection mechanism when no selector type is passed to a selector query\n      #\n      # @param [String] locator     The locator passed to the query\n      # @return [Boolean]           Whether or not to use this selector\n      #\n      def match?(locator)\n        @match&.call(locator)\n      end\n\n      ##\n      #\n      # Define a node filter for use with this selector\n      #\n      # @!method node_filter(name, *types, options={}, &block)\n      #   @param [Symbol, Regexp] name            The filter name\n      #   @param [Array<Symbol>] types    The types of the filter - currently valid types are [:boolean]\n      #   @param [Hash] options ({})      Options of the filter\n      #   @option options [Array<>] :valid_values Valid values for this filter\n      #   @option options :default        The default value of the filter (if any)\n      #   @option options :skip_if        Value of the filter that will cause it to be skipped\n      #   @option options [Regexp] :matcher (nil) A Regexp used to check whether a specific option is handled by this filter.  If not provided the filter will be used for options matching the filter name.\n      #\n      # If a Symbol is passed for the name the block should accept | node, option_value |, while if a Regexp\n      # is passed for the name the block should accept | node, option_name, option_value |. In either case\n      # the block should return `true` if the node passes the filer or `false` if it doesn't\n\n      ##\n      #\n      # Define an expression filter for use with this selector\n      #\n      # @!method expression_filter(name, *types, matcher: nil, **options, &block)\n      #   @param [Symbol, Regexp] name            The filter name\n      #   @param [Regexp] matcher (nil)   A Regexp used to check whether a specific option is handled by this filter\n      #   @param [Array<Symbol>] types    The types of the filter - currently valid types are [:boolean]\n      #   @param [Hash] options ({})      Options of the filter\n      #   @option options [Array<>] :valid_values Valid values for this filter\n      #   @option options :default        The default value of the filter (if any)\n      #   @option options :skip_if        Value of the filter that will cause it to be skipped\n      #   @option options [Regexp] :matcher (nil) A Regexp used to check whether a specific option is handled by this filter.  If not provided the filter will be used for options matching the filter name.\n      #\n      # If a Symbol is passed for the name the block should accept | current_expression, option_value |, while if a Regexp\n      # is passed for the name the block should accept | current_expression, option_name, option_value |. In either case\n      # the block should return the modified expression\n\n      def_delegators :@filter_set, :node_filter, :expression_filter, :filter\n\n      def locator_filter(*types, **options, &block)\n        types.each { |type| options[type] = true }\n        @locator_filter = Capybara::Selector::Filters::LocatorFilter.new(block, **options) if block\n        @locator_filter\n      end\n\n      def filter_set(name, filters_to_use = nil)\n        @filter_set.import(name, filters_to_use)\n      end\n\n      def_delegator :@filter_set, :describe\n\n      def describe_expression_filters(&block)\n        if block\n          describe(:expression_filters, &block)\n        else\n          describe(:expression_filters) do |**options|\n            describe_all_expression_filters(**options)\n          end\n        end\n      end\n\n      def describe_all_expression_filters(**opts)\n        expression_filters.map do |ef_name, ef|\n          if ef.matcher?\n            handled_custom_options(ef, opts).map { |option, value| \" with #{ef_name}[#{option} => #{value}]\" }.join\n          elsif opts.key?(ef_name)\n            \" with #{ef_name} #{opts[ef_name]}\"\n          end\n        end.join\n      end\n\n      def describe_node_filters(&block)\n        describe(:node_filters, &block)\n      end\n\n      ##\n      #\n      # Set the default visibility mode that should be used if no visible option is passed when using the selector.\n      # If not specified will default to the behavior indicated by Capybara.ignore_hidden_elements\n      #\n      # @param [Symbol] default_visibility  Only find elements with the specified visibility:\n      #                                              * :all - finds visible and invisible elements.\n      #                                              * :hidden - only finds invisible elements.\n      #                                              * :visible - only finds visible elements.\n      def visible(default_visibility = nil, &block)\n        @default_visibility = block || default_visibility\n      end\n\n      def default_visibility(fallback = Capybara.ignore_hidden_elements, options = {})\n        vis = if @default_visibility.respond_to?(:call)\n          @default_visibility.call(options)\n        else\n          @default_visibility\n        end\n        vis.nil? ? fallback : vis\n      end\n\n      # @api private\n      def raw_locator?\n        !!@raw_locator\n      end\n\n      # @api private\n      def supports_exact?\n        @supports_exact\n      end\n\n      def default_format\n        return nil if @expressions.keys.empty?\n\n        if @expressions.size == 1\n          @expressions.keys.first\n        else\n          :xpath\n        end\n      end\n\n      # @api private\n      def locator_types\n        return nil unless @locator_type\n\n        Array(@locator_type)\n      end\n\n    private\n\n      def handled_custom_options(filter, options)\n        options.select do |option, _|\n          filter.handles_option?(option) && !::Capybara::Queries::SelectorQuery::VALID_KEYS.include?(option)\n        end\n      end\n\n      def parameter_names(block)\n        key_types = %i[key keyreq]\n        # user filter_map when we drop dupport for 2.6\n        # block.parameters.select { |(type, _name)| key_types.include? type }.map { |(_, name)| name }\n        block.parameters.filter_map { |(type, name)| name if key_types.include? type }\n      end\n\n      def expression(type, allowed_filters, &block)\n        if block\n          @expressions[type] = block\n          allowed_filters = parameter_names(block) if allowed_filters.empty?\n          allowed_filters.flatten.each do |ef|\n            expression_filters[ef] = Capybara::Selector::Filters::IdentityExpressionFilter.new(ef)\n          end\n        end\n        @expressions[type]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filters/node_filter'\nrequire 'capybara/selector/filters/expression_filter'\nrequire 'capybara/selector/filters/locator_filter'\n"
  },
  {
    "path": "lib/capybara/selector/filter_set.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filter'\n\nmodule Capybara\n  class Selector\n    class FilterSet\n      attr_reader :node_filters, :expression_filters\n\n      def initialize(name, &block)\n        @name = name\n        @node_filters = {}\n        @expression_filters = {}\n        @descriptions = Hash.new { |hsh, key| hsh[key] = [] }\n        instance_eval(&block) if block\n      end\n\n      def node_filter(names, *types, **options, &block)\n        Array(names).each do |name|\n          add_filter(name, Filters::NodeFilter, *types, **options, &block)\n        end\n      end\n      alias_method :filter, :node_filter\n\n      def expression_filter(name, *types, **options, &block)\n        add_filter(name, Filters::ExpressionFilter, *types, **options, &block)\n      end\n\n      def describe(what = nil, &block)\n        case what\n        when nil\n          undeclared_descriptions.push block\n        when :node_filters\n          node_filter_descriptions.push block\n        when :expression_filters\n          expression_filter_descriptions.push block\n        else\n          raise ArgumentError, 'Unknown description type'\n        end\n      end\n\n      def description(node_filters: true, expression_filters: true, **options)\n        opts = options_with_defaults(options)\n        description = +''\n        description << undeclared_descriptions.map { |desc| desc.call(**opts).to_s }.join\n        description << expression_filter_descriptions.map { |desc| desc.call(**opts).to_s }.join if expression_filters\n        description << node_filter_descriptions.map { |desc| desc.call(**opts).to_s }.join if node_filters\n        description\n      end\n\n      def descriptions\n        Capybara::Helpers.warn 'DEPRECATED: FilterSet#descriptions is deprecated without replacement'\n        [undeclared_descriptions, node_filter_descriptions, expression_filter_descriptions].flatten\n      end\n\n      def import(name, filters = nil)\n        filter_selector = filters.nil? ? ->(*) { true } : ->(filter_name, _) { filters.include? filter_name }\n\n        self.class[name].tap do |f_set|\n          expression_filters.merge!(f_set.expression_filters.select(&filter_selector))\n          node_filters.merge!(f_set.node_filters.select(&filter_selector))\n          f_set.undeclared_descriptions.each { |desc| describe(&desc) }\n          f_set.expression_filter_descriptions.each { |desc| describe(:expression_filters, &desc) }\n          f_set.node_filter_descriptions.each { |desc| describe(:node_filters, &desc) }\n        end\n        self\n      end\n\n      class << self\n        def all\n          @filter_sets ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName\n        end\n\n        def [](name)\n          all.fetch(name.to_sym) { |set_name| raise ArgumentError, \"Unknown filter set (:#{set_name})\" }\n        end\n\n        def add(name, &block)\n          all[name.to_sym] = FilterSet.new(name.to_sym, &block)\n        end\n\n        def remove(name)\n          all.delete(name.to_sym)\n        end\n      end\n\n    protected\n\n      def undeclared_descriptions\n        @descriptions[:undeclared]\n      end\n\n      def node_filter_descriptions\n        @descriptions[:node_filters]\n      end\n\n      def expression_filter_descriptions\n        @descriptions[:expression_filters]\n      end\n\n    private\n\n      def options_with_defaults(options)\n        expression_filters\n          .chain(node_filters)\n          .filter_map { |name, filter| [name, filter.default] if filter.default? }\n          .to_h.merge!(options)\n      end\n\n      def add_filter(name, filter_class, *types, matcher: nil, **options, &block)\n        types.each { |type| options[type] = true }\n        if matcher && options[:default]\n          raise 'ArgumentError', ':default option is not supported for filters with a :matcher option'\n        end\n\n        filter = filter_class.new(name, matcher, block, **options)\n        (filter_class <= Filters::ExpressionFilter ? @expression_filters : @node_filters)[name] = filter\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/filters/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  class Selector\n    module Filters\n      class Base\n        def initialize(name, matcher, block, **options)\n          @name = name\n          @matcher = matcher\n          @block = block\n          @options = options\n          @options[:valid_values] = [true, false] if options[:boolean]\n        end\n\n        def default?\n          @options.key?(:default)\n        end\n\n        def default\n          @options[:default]\n        end\n\n        def skip?(value)\n          @options.key?(:skip_if) && value == @options[:skip_if]\n        end\n\n        def format\n          @options[:format]\n        end\n\n        def matcher?\n          !@matcher.nil?\n        end\n\n        def boolean?\n          !!@options[:boolean]\n        end\n\n        def handles_option?(option_name)\n          if matcher?\n            @matcher.match? option_name\n          else\n            @name == option_name\n          end\n        end\n\n      private\n\n        def apply(subject, name, value, skip_value, ctx)\n          return skip_value if skip?(value)\n\n          unless valid_value?(value)\n            raise ArgumentError,\n                  \"Invalid value #{value.inspect} passed to #{self.class.name.split('::').last} #{name}\" \\\n                  \"#{\" : #{name}\" if @name.is_a?(Regexp)}\"\n          end\n\n          if @block.arity == 2\n            filter_context(ctx).instance_exec(subject, value, &@block)\n          else\n            filter_context(ctx).instance_exec(subject, name, value, &@block)\n          end\n        end\n\n        def filter_context(context)\n          context || @block.binding.receiver\n        end\n\n        def valid_value?(value)\n          return true unless @options.key?(:valid_values)\n\n          Array(@options[:valid_values]).any? { |valid| valid === value } # rubocop:disable Style/CaseEquality\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/filters/expression_filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filters/base'\n\nmodule Capybara\n  class Selector\n    module Filters\n      class ExpressionFilter < Base\n        def apply_filter(expr, name, value, selector)\n          apply(expr, name, value, expr, selector)\n        end\n      end\n\n      class IdentityExpressionFilter < ExpressionFilter\n        def initialize(name); super(name, nil, nil); end\n        def default?; false; end\n        def matcher?; false; end\n        def apply_filter(expr, _name, _value, _ctx); expr; end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/filters/locator_filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filters/base'\n\nmodule Capybara\n  class Selector\n    module Filters\n      class LocatorFilter < NodeFilter\n        def initialize(block, **options)\n          super(nil, nil, block, **options)\n        end\n\n        def matches?(node, value, context = nil, exact:)\n          apply(node, value, true, context, exact: exact, format: context&.default_format)\n        rescue Capybara::ElementNotFound\n          false\n        end\n\n      private\n\n        def apply(subject, value, skip_value, ctx, **options)\n          return skip_value if skip?(value)\n\n          filter_context(ctx).instance_exec(subject, value, **options, &@block)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/filters/node_filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/filters/base'\n\nmodule Capybara\n  class Selector\n    module Filters\n      class NodeFilter < Base\n        def initialize(name, matcher, block, **options)\n          super\n          @block = if boolean?\n            proc do |node, value|\n              error_cnt = errors.size\n              block.call(node, value).tap do |res|\n                add_error(\"Expected #{name} #{value} but it wasn't\") if !res && error_cnt == errors.size\n              end\n            end\n          else\n            block\n          end\n        end\n\n        def matches?(node, name, value, context = nil)\n          apply(node, name, value, true, context)\n        rescue Capybara::ElementNotFound\n          false\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/regexp_disassembler.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'regexp_parser'\n\nmodule Capybara\n  class Selector\n    # @api private\n    class RegexpDisassembler\n      def initialize(regexp)\n        @regexp = regexp\n      end\n\n      def alternated_substrings\n        @alternated_substrings ||= begin\n          or_strings = process(alternation: true)\n          remove_or_covered(or_strings)\n          or_strings.any?(&:empty?) ? [] : or_strings\n        end\n      end\n\n      def substrings\n        @substrings ||= begin\n          strs = process(alternation: false).first\n          remove_and_covered(strs)\n        end\n      end\n\n    private\n\n      def remove_and_covered(strings)\n        # delete_if is documented to modify the array after every block iteration - this doesn't appear to be true\n        # uniq the strings to prevent identical strings from removing each other\n        strings.uniq!\n\n        # If we have \"ab\" and \"abcd\" required - only need to check for \"abcd\"\n        strings.delete_if do |sub_string|\n          strings.any? do |cover_string|\n            next if sub_string.equal? cover_string\n\n            cover_string.include?(sub_string)\n          end\n        end\n      end\n\n      def remove_or_covered(or_series)\n        # If we are going to match `(\"a\" and \"b\") or (\"ade\" and \"bce\")` it only makes sense to match (\"a\" and \"b\")\n\n        # Ensure minimum sets of strings are being or'd\n        or_series.each { |strs| remove_and_covered(strs) }\n\n        # Remove any of the alternated string series that fully contain any other string series\n        or_series.delete_if do |and_strs|\n          or_series.any? do |and_strs2|\n            next if and_strs.equal? and_strs2\n\n            remove_and_covered(and_strs + and_strs2) == and_strs\n          end\n        end\n      end\n\n      def process(alternation:)\n        strs = extract_strings(Regexp::Parser.parse(@regexp), alternation: alternation)\n        strs = collapse(combine(strs).map(&:flatten))\n        strs.each { |str| str.map!(&:upcase) } if @regexp.casefold?\n        strs\n      end\n\n      def combine(strs)\n        suffixes = [[]]\n        strs.reverse_each do |str|\n          if str.is_a? Set\n            prefixes = str.flat_map { |s| combine(s) }\n            suffixes = prefixes.product(suffixes).map { |pair| pair.flatten(1) }\n          else\n            suffixes.each { |arr| arr.unshift str }\n          end\n        end\n        suffixes\n      end\n\n      def collapse(strs)\n        strs.map do |substrings|\n          substrings.slice_before(&:nil?).map(&:join).reject(&:empty?).uniq\n        end\n      end\n\n      def extract_strings(expression, alternation: false)\n        Expression.new(expression).extract_strings(alternation)\n      end\n\n      # @api private\n      class Expression\n        def initialize(exp)\n          @exp = exp\n        end\n\n        def extract_strings(process_alternatives)\n          strings = []\n          each do |exp|\n            next if exp.ignore?\n\n            next strings.push(nil) if exp.optional? && !process_alternatives\n\n            next strings.push(exp.alternative_strings) if exp.alternation? && process_alternatives\n\n            strings.concat(exp.strings(process_alternatives))\n          end\n          strings\n        end\n\n      protected\n\n        def alternation?\n          (type == :meta) && !terminal?\n        end\n\n        def optional?\n          min_repeat.zero?\n        end\n\n        def terminal?\n          @exp.terminal?\n        end\n\n        def strings(process_alternatives)\n          if indeterminate?\n            [nil]\n          elsif terminal?\n            terminal_strings\n          elsif optional?\n            optional_strings\n          else\n            repeated_strings(process_alternatives)\n          end\n        end\n\n        def terminal_strings\n          text = case @exp.type\n          when :literal then @exp.text\n          when :escape then @exp.char\n          else\n            return [nil]\n          end\n\n          optional? ? options_set(text) : repeat_set(text)\n        end\n\n        def optional_strings\n          options_set(extract_strings(true))\n        end\n\n        def repeated_strings(process_alternatives)\n          repeat_set extract_strings(process_alternatives)\n        end\n\n        def alternative_strings\n          alts = alternatives.map { |sub_exp| sub_exp.extract_strings(alternation: true) }\n          alts.all?(&:any?) ? Set.new(alts) : nil\n        end\n\n        def ignore?\n          [Regexp::Expression::Assertion::NegativeLookahead,\n           Regexp::Expression::Assertion::NegativeLookbehind].any? { |klass| @exp.is_a? klass }\n        end\n\n      private\n\n        def indeterminate?\n          %i[meta set].include?(type)\n        end\n\n        def min_repeat\n          @exp.repetitions.begin\n        end\n\n        def max_repeat\n          @exp.repetitions.end\n        end\n\n        def fixed_repeat?\n          min_repeat == max_repeat\n        end\n\n        def type\n          @exp.type\n        end\n\n        def repeat_set(str)\n          strs = Array(str * min_repeat)\n          strs.push(nil) unless fixed_repeat?\n          strs\n        end\n\n        def options_set(strs)\n          strs = [Set.new([[''], Array(strs)])]\n          strs.push(nil) unless max_repeat == 1\n          strs\n        end\n\n        def alternatives\n          @exp.alternatives.map { |exp| Expression.new(exp) }\n        end\n\n        def each\n          @exp.each { |exp| yield Expression.new(exp) }\n        end\n      end\n      private_constant :Expression\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/selector.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  class Selector < SimpleDelegator\n    class << self\n      def all\n        @definitions ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName\n      end\n\n      def [](name)\n        all.fetch(name.to_sym) { |sel_type| raise ArgumentError, \"Unknown selector type (:#{sel_type})\" }\n      end\n\n      def add(name, **options, &block)\n        all[name.to_sym] = Definition.new(name.to_sym, **options, &block)\n      end\n\n      def update(name, &block)\n        self[name].instance_eval(&block)\n      end\n\n      def remove(name)\n        all.delete(name.to_sym)\n      end\n\n      def for(locator)\n        all.values.find { |sel| sel.match?(locator) }\n      end\n    end\n\n    attr_reader :errors\n\n    def initialize(definition, config:, format:)\n      definition = self.class[definition] unless definition.is_a? Definition\n      super(definition)\n      @definition = definition\n      @config = config\n      @format = format\n      @errors = []\n    end\n\n    def format\n      @format || @definition.default_format\n    end\n    alias_method :current_format, :format\n\n    def enable_aria_label\n      @config[:enable_aria_label]\n    end\n\n    def enable_aria_role\n      @config[:enable_aria_role]\n    end\n\n    def test_id\n      @config[:test_id]\n    end\n\n    def call(locator, **options)\n      if format\n        raise ArgumentError, \"Selector #{@name} does not support #{format}\" unless expressions.key?(format)\n\n        instance_exec(locator, **options, &expressions[format])\n      else\n        warn 'Selector has no format'\n      end\n    ensure\n      unless locator_valid?(locator)\n        Capybara::Helpers.warn(\n          \"Locator #{locator.class}:#{locator.inspect} for selector #{name.inspect} must #{locator_description}. \" \\\n          'This will raise an error in a future version of Capybara. ' \\\n          \"Called from: #{Capybara::Helpers.filter_backtrace(caller)}\"\n        )\n      end\n    end\n\n    def add_error(error_msg)\n      errors << error_msg\n    end\n\n    def expression_for(name, locator, config: @config, format: current_format, **options)\n      Selector.new(name, config: config, format: format).call(locator, **options)\n    end\n\n    # @api private\n    def with_filter_errors(errors)\n      old_errors = @errors\n      @errors = errors\n      yield\n    ensure\n      @errors = old_errors\n    end\n\n    # @api private\n    def builder(expr = nil)\n      case format\n      when :css\n        Capybara::Selector::CSSBuilder\n      when :xpath\n        Capybara::Selector::XPathBuilder\n      else\n        raise NotImplementedError, \"No builder exists for selector of type #{default_format}\"\n      end.new(expr)\n    end\n\n  private\n\n    def locator_description\n      locator_types.group_by { |lt| lt.is_a? Symbol }.map do |symbol, types_or_methods|\n        if symbol\n          \"respond to #{types_or_methods.join(' or ')}\"\n        else\n          \"be an instance of #{types_or_methods.join(' or ')}\"\n        end\n      end.join(' or ')\n    end\n\n    def locator_valid?(locator)\n      return true unless locator && locator_types\n\n      locator_types&.any? do |type_or_method|\n        type_or_method.is_a?(Symbol) ? locator.respond_to?(type_or_method) : type_or_method === locator # rubocop:disable Style/CaseEquality\n      end\n    end\n\n    def locate_field(xpath, locator, **_options)\n      return xpath if locator.nil?\n\n      locate_xpath = xpath # Need to save original xpath for the label wrap\n      locator = locator.to_s\n      attr_matchers = [XPath.attr(:id) == locator,\n                       XPath.attr(:name) == locator,\n                       XPath.attr(:placeholder) == locator,\n                       XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)].reduce(:|)\n      attr_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label\n      attr_matchers |= XPath.attr(test_id) == locator if test_id\n\n      locate_xpath = locate_xpath[attr_matchers]\n      locate_xpath + locate_label(locator).descendant(xpath)\n    end\n\n    def locate_label(locator)\n      XPath.descendant(:label)[XPath.string.n.is(locator)]\n    end\n\n    def find_by_attr(attribute, value)\n      finder_name = \"find_by_#{attribute}_attr\"\n      if respond_to?(finder_name, true)\n        send(finder_name, value)\n      else\n        value ? XPath.attr(attribute) == value : nil\n      end\n    end\n\n    def find_by_class_attr(classes)\n      Array(classes).map { |klass| XPath.attr(:class).contains_word(klass) }.reduce(:&)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector/xpath_extensions.rb",
    "content": "# frozen_string_literal: true\n\nmodule XPath\n  class Renderer\n    def join(*expressions)\n      expressions.join('/')\n    end\n  end\nend\n\nmodule XPath\n  module DSL\n    def join(*expressions)\n      XPath::Expression.new(:join, *[self, expressions].flatten)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selector.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selector/xpath_extensions'\nrequire 'capybara/selector/selector'\nrequire 'capybara/selector/definition'\n\n#\n# All Selectors below support the listed selector specific filters in addition to the following system-wide filters\n#   * :id (String, Regexp, XPath::Expression) - Matches the id attribute\n#   * :class (String, Array<String | Regexp>, Regexp, XPath::Expression) - Matches the class(es) provided\n#   * :style (String, Regexp, Hash<String, String>) - Match on elements style\n#   * :above (Element) - Match elements above the passed element on the page\n#   * :below (Element) - Match elements below the passed element on the page\n#   * :left_of (Element) - Match elements left of the passed element on the page\n#   * :right_of (Element) - Match elements right of the passed element on the page\n#   * :near (Element) - Match elements near (within 50px) the passed element on the page\n#   * :focused (Boolean) - Match elements with focus (requires driver support)\n#\n# ### Built-in Selectors\n#\n# * **:xpath** - Select elements by XPath expression\n#   * Locator: An XPath expression\n#\n#   ```ruby\n#   page.html # => '<input>'\n#\n#   page.find :xpath, './/input'\n#   ```\n#\n# * **:css** - Select elements by CSS selector\n#   * Locator: A CSS selector\n#\n#   ```ruby\n#   page.html # => '<input>'\n#\n#   page.find :css, 'input'\n#   ```\n#\n# * **:id** - Select element by id\n#   * Locator: (String, Regexp, XPath::Expression) The id of the element to match\n#\n#   ```ruby\n#   page.html # => '<input id=\"field\">'\n#\n#   page.find :id, 'field'\n#   ```\n#\n# * **:field** - Select field elements (input [not of type submit, image, or hidden], textarea, select)\n#   * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or\n#     associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :placeholder (String, Regexp) - Matches the placeholder attribute\n#       * :type (String) - Matches the type attribute of the field or element type for 'textarea' and 'select'\n#       * :readonly (Boolean) - Match on the element being readonly\n#       * :with (String, Regexp) - Matches the current value of the field\n#       * :checked (Boolean) - Match checked fields?\n#       * :unchecked (Boolean) - Match unchecked fields?\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :multiple (Boolean) - Match fields that accept multiple values\n#       * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation\n#       * :validation_message (String, Regexp) - Matches the elements current validationMessage\n#\n#   ```ruby\n#   page.html # => '<label for=\"article_title\">Title</label>\n#             #     <input id=\"article_title\" name=\"article[title]\" value=\"Hello world\">'\n#\n#   page.find :field, 'article_title'\n#   page.find :field, 'article[title]'\n#   page.find :field, 'Title'\n#   page.find :field, 'Title', type: 'text', with: 'Hello world'\n#   ```\n#\n# * **:fieldset** - Select fieldset elements\n#   * Locator: Matches id, {Capybara.configure test_id}, or contents of wrapped legend\n#   * Filters:\n#       * :legend (String) - Matches contents of wrapped legend\n#       * :disabled (Boolean) - Match disabled fieldset?\n#\n#   ```ruby\n#   page.html # => '<fieldset disabled>\n#             #       <legend>Fields (disabled)</legend>\n#             #     </fieldset>'\n#\n#   page.find :fieldset, 'Fields (disabled)', disabled: true\n#   ```\n#\n# * **:link** - Find links (`<a>` elements with an href attribute)\n#   * Locator: Matches the id, {Capybara.configure test_id}, or title attributes, or the string content of the link,\n#     or the alt attribute of a contained img element. By default this selector requires a link to have an href attribute.\n#   * Filters:\n#       * :title (String) - Matches the title attribute\n#       * :alt (String) - Matches the alt attribute of a contained img element\n#       * :href (String, Regexp, nil, false) - Matches the normalized href of the link, if nil will find `<a>` elements with no href attribute, if false ignores href presence\n#\n#   ```ruby\n#   page.html # => '<a href=\"/\">Home</a>'\n#\n#   page.find :link, 'Home', href: '/'\n#\n#   page.html # => '<a href=\"/\"><img src=\"/logo.png\" alt=\"The logo\"></a>'\n#\n#   page.find :link, 'The logo', href: '/'\n#   page.find :link, alt: 'The logo', href: '/'\n#   ```\n#\n# * **:button** - Find buttons ( input [of type submit, reset, image, button] or button elements )\n#   * Locator: Matches the id, {Capybara.configure test_id} attribute, name, value, or title attributes, string content of a button, or the alt attribute of an image type button or of a descendant image of a button\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :title (String) - Matches the title attribute\n#       * :value (String) - Matches the value of an input button\n#       * :type (String) - Matches the type attribute\n#       * :disabled (Boolean, :all) - Match disabled buttons (Default: false)\n#\n#   ```ruby\n#   page.html # => '<button>Submit</button>'\n#\n#   page.find :button, 'Submit'\n#\n#   page.html # => '<button name=\"article[state]\" value=\"draft\">Save as draft</button>'\n#\n#   page.find :button, 'Save as draft', name: 'article[state]', value: 'draft'\n#   ```\n#\n# * **:link_or_button** - Find links or buttons\n#   * Locator: See :link and :button selectors\n#   * Filters:\n#       * :disabled (Boolean, :all) - Match disabled buttons? (Default: false)\n#\n#   ```ruby\n#   page.html # => '<a href=\"/\">Home</a>'\n#\n#   page.find :link_or_button, 'Home'\n#\n#   page.html # => '<button>Submit</button>'\n#\n#   page.find :link_or_button, 'Submit'\n#   ```\n#\n# * **:fillable_field** - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )\n#   * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :placeholder (String, Regexp) - Matches the placeholder attribute\n#       * :with (String, Regexp) - Matches the current value of the field\n#       * :type (String) - Matches the type attribute of the field or element type for 'textarea'\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :multiple (Boolean) - Match fields that accept multiple values\n#       * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation\n#       * :validation_message (String, Regexp) - Matches the elements current validationMessage\n#\n#   ```ruby\n#   page.html # => '<label for=\"article_body\">Body</label>\n#             #     <textarea id=\"article_body\" name=\"article[body]\"></textarea>'\n#\n#   page.find :fillable_field, 'article_body'\n#   page.find :fillable_field, 'article[body]'\n#   page.find :fillable_field, 'Body'\n#   page.find :field, 'Body', type: 'textarea'\n#   ```\n#\n# * **:radio_button** - Find radio buttons\n#   * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :checked (Boolean) - Match checked fields?\n#       * :unchecked (Boolean) - Match unchecked fields?\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :option (String, Regexp) - Match the current value\n#       * :with - Alias of :option\n#\n#   ```ruby\n#   page.html # => '<input type=\"radio\" id=\"article_state_published\" name=\"article[state]\" value=\"published\" checked>\n#             #     <label for=\"article_state_published\">Published</label>\n#             #     <input type=\"radio\" id=\"article_state_draft\" name=\"article[state]\" value=\"draft\">\n#             #     <label for=\"article_state_draft\">Draft</label>'\n#\n#   page.find :radio_button, 'article_state_published'\n#   page.find :radio_button, 'article[state]', option: 'published'\n#   page.find :radio_button, 'Published', checked: true\n#   page.find :radio_button, 'Draft', unchecked: true\n#   ```\n#\n# * **:checkbox** - Find checkboxes\n#   * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :checked (Boolean) - Match checked fields?\n#       * :unchecked (Boolean) - Match unchecked fields?\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :with (String, Regexp) - Match the current value\n#       * :option - Alias of :with\n#\n#   ```ruby\n#   page.html # => '<input type=\"checkbox\" id=\"registration_terms\" name=\"registration[terms]\" value=\"true\">\n#             #     <label for=\"registration_terms\">I agree to terms and conditions</label>'\n#\n#   page.find :checkbox, 'registration_terms'\n#   page.find :checkbox, 'registration[terms]'\n#   page.find :checkbox, 'I agree to terms and conditions', unchecked: true\n#   ```\n#\n# * **:select** - Find select elements\n#   * Locator: Match id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :placeholder (String, Placeholder) - Matches the placeholder attribute\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :multiple (Boolean) - Match fields that accept multiple values\n#       * :options (Array<String>) - Exact match options\n#       * :enabled_options (Array<String>) - Exact match enabled options\n#       * :disabled_options (Array<String>) - Exact match disabled options\n#       * :with_options (Array<String>) - Partial match options\n#       * :selected (String, Array<String>) - Match the selection(s)\n#       * :with_selected (String, Array<String>) - Partial match the selection(s)\n#\n#   ```ruby\n#   page.html # => '<label for=\"article_category\">Category</label>\n#             #     <select id=\"article_category\" name=\"article[category]\">\n#             #       <option value=\"General\" checked></option>\n#             #       <option value=\"Other\"></option>\n#             #     </select>'\n#\n#   page.find :select, 'article_category'\n#   page.find :select, 'article[category]'\n#   page.find :select, 'Category'\n#   page.find :select, 'Category', selected: 'General'\n#   page.find :select, with_options: ['General']\n#   page.find :select, with_options: ['Other']\n#   page.find :select, options: ['General', 'Other']\n#   page.find :select, options: ['General'] # => raises Capybara::ElementNotFound\n#   ```\n#\n# * **:option** - Find option elements\n#   * Locator: Match text of option\n#   * Filters:\n#       * :disabled (Boolean) - Match disabled option\n#       * :selected (Boolean) - Match selected option\n#\n#   ```ruby\n#   page.html # => '<option value=\"General\" checked></option>\n#             #     <option value=\"Disabled\" disabled></option>\n#             #     <option value=\"Other\"></option>'\n#\n#   page.find :option, 'General'\n#   page.find :option, 'General', selected: true\n#   page.find :option, 'Disabled', disabled: true\n#   page.find :option, 'Other', selected: false\n#   ```\n#\n# * **:datalist_input** - Find input field with datalist completion\n#   * Locator: Matches against the id, {Capybara.configure test_id} attribute, name,\n#     placeholder, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :placeholder (String, Regexp) - Matches the placeholder attribute\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :options (Array<String>) - Exact match options\n#       * :with_options (Array<String>) - Partial match options\n#\n#   ```ruby\n#   page.html # => '<label for=\"ice_cream_flavor\">Flavor</label>\n#             #     <input list=\"ice_cream_flavors\" id=\"ice_cream_flavor\" name=\"ice_cream[flavor]\">\n#             #     <datalist id=\"ice_cream_flavors\">\n#             #       <option value=\"Chocolate\"></option>\n#             #       <option value=\"Strawberry\"></option>\n#             #       <option value=\"Vanilla\"></option>\n#             #     </datalist>'\n#\n#   page.find :datalist_input, 'ice_cream_flavor'\n#   page.find :datalist_input, 'ice_cream[flavor]'\n#   page.find :datalist_input, 'Flavor'\n#   page.find :datalist_input, with_options: ['Chocolate', 'Strawberry']\n#   page.find :datalist_input, options: ['Chocolate', 'Strawberry', 'Vanilla']\n#   page.find :datalist_input, options: ['Chocolate'] # => raises Capybara::ElementNotFound\n#   ```\n#\n# * **:datalist_option** - Find datalist option\n#   * Locator: Match text or value of option\n#   * Filters:\n#       * :disabled (Boolean) - Match disabled option\n#\n#   ```ruby\n#   page.html # => '<datalist>\n#             #       <option value=\"Chocolate\"></option>\n#             #       <option value=\"Strawberry\"></option>\n#             #       <option value=\"Vanilla\"></option>\n#             #       <option value=\"Forbidden\" disabled></option>\n#             #     </datalist>'\n#\n#   page.find :datalist_option, 'Chocolate'\n#   page.find :datalist_option, 'Strawberry'\n#   page.find :datalist_option, 'Vanilla'\n#   page.find :datalist_option, 'Forbidden', disabled: true\n#   ```\n#\n# * **:file_field** - Find file input elements\n#   * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text\n#   * Filters:\n#       * :name (String, Regexp) - Matches the name attribute\n#       * :disabled (Boolean, :all) - Match disabled field? (Default: false)\n#       * :multiple (Boolean) - Match field that accepts multiple values\n#\n#   ```ruby\n#   page.html # => '<label for=\"article_banner_image\">Banner Image</label>\n#             #     <input type=\"file\" id=\"article_banner_image\" name=\"article[banner_image]\">'\n#\n#   page.find :file_field, 'article_banner_image'\n#   page.find :file_field, 'article[banner_image]'\n#   page.find :file_field, 'Banner Image'\n#   page.find :file_field, 'Banner Image', name: 'article[banner_image]'\n#   page.find :field, 'Banner Image', type: 'file'\n#   ```\n#\n# * **:label** - Find label elements\n#   * Locator: Match id, {Capybara.configure test_id}, or text contents\n#   * Filters:\n#       * :for (Element, String, Regexp) - The element or id of the element associated with the label\n#\n#   ```ruby\n#   page.html # => '<label for=\"article_title\">Title</label>\n#             #     <input id=\"article_title\" name=\"article[title]\">'\n#\n#   page.find :label, 'Title'\n#   page.find :label, 'Title', for: 'article_title'\n#   page.find :label, 'Title', for: page.find('article[title]')\n#   ```\n#\n# * **:table** - Find table elements\n#   * Locator: id, {Capybara.configure test_id}, or caption text of table\n#   * Filters:\n#       * :caption (String) - Match text of associated caption\n#       * :with_rows (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered\n#       * :rows (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered\n#       * :with_cols (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered\n#       * :cols (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered\n#\n#   ```ruby\n#   page.html # => '<table>\n#             #       <caption>A table</caption>\n#             #       <tr>\n#             #         <th>A</th>\n#             #         <th>B</th>\n#             #       </tr>\n#             #       <tr>\n#             #         <td>1</td>\n#             #         <td>2</td>\n#             #       </tr>\n#             #       <tr>\n#             #         <td>3</td>\n#             #         <td>4</td>\n#             #       </tr>\n#             #     </table>'\n#\n#   page.find :table, 'A table'\n#   page.find :table, with_rows: [\n#     { 'A' => '1', 'B' => '2' },\n#     { 'A' => '3', 'B' => '4' },\n#   ]\n#   page.find :table, with_rows: [\n#     ['1', '2'],\n#     ['3', '4'],\n#   ]\n#   page.find :table, rows: [\n#     { 'A' => '1', 'B' => '2' },\n#     { 'A' => '3', 'B' => '4' },\n#   ]\n#   page.find :table, rows: [\n#     ['1', '2'],\n#     ['3', '4'],\n#   ]\n#   page.find :table, rows: [ ['1', '2'] ] # => raises Capybara::ElementNotFound\n#   ```\n#\n# * **:table_row** - Find table row\n#   * Locator: Array<String>, Hash<String, String> table row `<td>` contents - visibility of `<td>` elements is not considered\n#\n#   ```ruby\n#   page.html # => '<table>\n#             #       <tr>\n#             #         <th>A</th>\n#             #         <th>B</th>\n#             #       </tr>\n#             #       <tr>\n#             #         <td>1</td>\n#             #         <td>2</td>\n#             #       </tr>\n#             #       <tr>\n#             #         <td>3</td>\n#             #         <td>4</td>\n#             #       </tr>\n#             #     </table>'\n#\n#   page.find :table_row, 'A' => '1', 'B' => '2'\n#   page.find :table_row, 'A' => '3', 'B' => '4'\n#   ```\n#\n# * **:frame** - Find frame/iframe elements\n#   * Locator: Match id, {Capybara.configure test_id} attribute, or name\n#   * Filters:\n#       * :name (String) - Match name attribute\n#\n#   ```ruby\n#   page.html # => '<iframe id=\"embed_frame\" name=\"embed\" src=\"https://example.com/embed\"></iframe>'\n#\n#   page.find :frame, 'embed_frame'\n#   page.find :frame, 'embed'\n#   page.find :frame, name: 'embed'\n#   ```\n#\n# * **:element**\n#   * Locator: Type of element ('div', 'a', etc) - if not specified defaults to '*'\n#   * Filters:\n#       * :\\<any> (String, Regexp) - Match on any specified element attribute\n#\n#   ```ruby\n#   page.html # => '<button type=\"button\" role=\"menuitemcheckbox\" aria-checked=\"true\">Check me</button>\n#\n#   page.find :element, 'button'\n#   page.find :element, type: 'button', text: 'Check me'\n#   page.find :element, role: 'menuitemcheckbox'\n#   page.find :element, role: /checkbox/, 'aria-checked': 'true'\n#   ```\n#\nclass Capybara::Selector; end # rubocop:disable Lint/EmptyClass\n\nCapybara::Selector::FilterSet.add(:_field) do\n  node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }\n  node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }\n  node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }\n  node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value }\n  node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }\n  node_filter(:placeholder) { |node, value| !value.is_a?(Regexp) || value.match?(node[:placeholder]) }\n  node_filter(:validation_message) do |node, msg|\n    vm = node[:validationMessage]\n    (msg.is_a?(Regexp) ? msg.match?(vm) : vm == msg.to_s).tap do |res|\n      add_error(\"Expected validation message to be #{msg.inspect} but was #{vm}\") unless res\n    end\n  end\n\n  expression_filter(:name) do |xpath, val|\n    builder(xpath).add_attribute_conditions(name: val)\n  end\n  expression_filter(:placeholder) do |xpath, val|\n    builder(xpath).add_attribute_conditions(placeholder: val)\n  end\n  expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }\n  expression_filter(:multiple) { |xpath, val| xpath[val ? XPath.attr(:multiple) : ~XPath.attr(:multiple)] }\n\n  describe(:expression_filters) do |name: nil, placeholder: nil, disabled: nil, multiple: nil, **|\n    desc = +''\n    desc << ' that is not disabled' if disabled == false\n    desc << \" with name #{name}\" if name\n    desc << \" with placeholder #{placeholder}\" if placeholder\n    desc << ' with the multiple attribute' if multiple == true\n    desc << ' without the multiple attribute' if multiple == false\n    desc\n  end\n\n  describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, validation_message: nil, **|\n    desc, states = +'', []\n    states << 'checked' if checked || (unchecked == false)\n    states << 'not checked' if unchecked || (checked == false)\n    states << 'disabled' if disabled == true\n    desc << \" that is #{states.join(' and ')}\" unless states.empty?\n    desc << ' that is valid' if valid == true\n    desc << ' that is invalid' if valid == false\n    desc << \" with validation message #{validation_message.to_s.inspect}\" if validation_message\n    desc\n  end\nend\n\nrequire 'capybara/selector/definition/xpath'\nrequire 'capybara/selector/definition/css'\nrequire 'capybara/selector/definition/id'\nrequire 'capybara/selector/definition/field'\nrequire 'capybara/selector/definition/fieldset'\nrequire 'capybara/selector/definition/link'\nrequire 'capybara/selector/definition/button'\nrequire 'capybara/selector/definition/link_or_button'\nrequire 'capybara/selector/definition/fillable_field'\nrequire 'capybara/selector/definition/radio_button'\nrequire 'capybara/selector/definition/checkbox'\nrequire 'capybara/selector/definition/select'\nrequire 'capybara/selector/definition/datalist_input'\nrequire 'capybara/selector/definition/option'\nrequire 'capybara/selector/definition/datalist_option'\nrequire 'capybara/selector/definition/file_field'\nrequire 'capybara/selector/definition/label'\nrequire 'capybara/selector/definition/table'\nrequire 'capybara/selector/definition/table_row'\nrequire 'capybara/selector/definition/frame'\nrequire 'capybara/selector/definition/element'\n"
  },
  {
    "path": "lib/capybara/selenium/atoms/src/getAttribute.js",
    "content": "(function(){\n  var BOOLEAN_PROPERTIES = [\n    \"allowfullscreen\",\n    \"allowpaymentrequest\",\n    \"allowusermedia\",\n    \"async\",\n    \"autofocus\",\n    \"autoplay\",\n    \"checked\",\n    \"compact\",\n    \"complete\",\n    \"controls\",\n    \"declare\",\n    \"default\",\n    \"defaultchecked\",\n    \"defaultselected\",\n    \"defer\",\n    \"disabled\",\n    \"ended\",\n    \"formnovalidate\",\n    \"hidden\",\n    \"indeterminate\",\n    \"iscontenteditable\",\n    \"ismap\",\n    \"itemscope\",\n    \"loop\",\n    \"multiple\",\n    \"muted\",\n    \"nohref\",\n    \"nomodule\",\n    \"noresize\",\n    \"noshade\",\n    \"novalidate\",\n    \"nowrap\",\n    \"open\",\n    \"paused\",\n    \"playsinline\",\n    \"pubdate\",\n    \"readonly\",\n    \"required\",\n    \"reversed\",\n    \"scoped\",\n    \"seamless\",\n    \"seeking\",\n    \"selected\",\n    \"truespeed\",\n    \"typemustmatch\",\n    \"willvalidate\"\n  ];\n\n  var PROPERTY_ALIASES = {\n    \"class\": \"className\",\n    \"readonly\": \"readOnly\"\n  };\n\n  function isSelectable(element){\n    var tagName = element.tagName.toUpperCase();\n\n    if (tagName == \"OPTION\"){\n      return true;\n    }\n\n    if (tagName == \"INPUT\") {\n      var type = element.type.toLowerCase();\n      return type == \"checkbox\" || type == \"radio\";\n    }\n\n    return false;\n  }\n\n  function isSelected(element){\n    var propertyName = \"selected\";\n    var type = element.type && element.type.toLowerCase();\n    if (\"checkbox\" == type || \"radio\" == type) {\n      propertyName = \"checked\";\n    }\n\n    return !!element[propertyName];\n  }\n\n  function getAttributeValue(element, name){\n    var attr = element.getAttributeNode(name);\n    return (attr && attr.specified) ? attr.value : null;\n  }\n\n  return function get(element, attribute){\n    var value = null;\n    var name = attribute.toLowerCase();\n\n    if (\"style\" == name) {\n      value = element.style;\n\n      if (value && (typeof value != \"string\")) {\n        value = value.cssText;\n      }\n\n      return value;\n    }\n\n    if ((\"selected\" == name || \"checked\" == name) &&\n        isSelectable(element)) {\n      return isSelected(element) ? \"true\" : null;\n    }\n\n    tagName = element.tagName.toUpperCase();\n\n    // The property is consistent. Return that in preference to the attribute for links and images.\n    if (((tagName == \"IMG\") && name == \"src\") ||\n        ((tagName == \"A\") && name == \"href\")) {\n      value = getAttributeValue(element, name);\n      if (value) {\n        // We want the full URL if present\n        value = element[name];\n      }\n      return value;\n    }\n\n    if (\"spellcheck\" == name) {\n      value = getAttributeValue(element, name);\n      if (!(value === null)) {\n        if (value.toLowerCase() == \"false\") {\n          return \"false\";\n        } else if (value.toLowerCase() == \"true\") {\n          return \"true\";\n        }\n      }\n      // coerce the property value to a string\n      return element[name] + \"\";\n    }\n    var propName = PROPERTY_ALIASES[attribute] || attribute;\n    if (BOOLEAN_PROPERTIES.some(function(prop){ prop == name })) {\n      value = getAttributeValue(element, name);\n      value = !(value === null) || element[propName];\n      return value ? \"true\" : null;\n    }\n    var property;\n    try {\n      property = element[propName]\n    } catch (e) {\n      // Leaves property undefined or null\n    }\n    // 1- Call getAttribute if getProperty fails,\n    // i.e. property is null or undefined.\n    // This happens for event handlers in Firefox.\n    // For example, calling getProperty for 'onclick' would\n    // fail while getAttribute for 'onclick' will succeed and\n    // return the JS code of the handler.\n    //\n    // 2- When property is an object we fall back to the\n    // actual attribute instead.\n    // See issue http://code.google.com/p/selenium/issues/detail?id=966\n    if ((property == null) || (typeof property == \"object\") || (typeof property == \"function\")) {\n      value = getAttributeValue(element, attribute);\n    } else {\n      value = property;\n    };\n\n    // The empty string is a valid return value.\n    return value != null ? value.toString() : null;\n  };\n})()"
  },
  {
    "path": "lib/capybara/selenium/atoms/src/isDisplayed.js",
    "content": "(function(){\n  var OverflowState = {\n    NONE: \"none\",\n    HIDDEN: \"hidden\",\n    SCROLL: \"scroll\"\n  };\n\n  function isShown_(elem, ignoreOpacity, parentsDisplayedFn) {\n    // By convention, BODY element is always shown: BODY represents the document\n    // and even if there's nothing rendered in there, user can always see there's\n    // the document.\n    var elemTagName = elem.tagName.toUpperCase();\n    if (elemTagName == \"BODY\") {\n      return true;\n    }\n\n    // Option or optgroup is shown if enclosing select is shown (ignoring the\n    // select's opacity).\n    if ((elemTagName == \"OPTION\") ||\n        (elemTagName == \"OPTGROUP\")) {\n      var select = getAncestor(elem, function(e) {\n        return e.tagName.toUpperCase() == \"SELECT\";\n      });\n      return !!select && isShown_(select, true, parentsDisplayedFn);\n    }\n\n    // Image map elements are shown if image that uses it is shown, and\n    // the area of the element is positive.\n    var imageMap = maybeFindImageMap_(elem);\n    if (imageMap) {\n      return !!imageMap.image &&\n             imageMap.rect.width > 0 && imageMap.rect.height > 0 &&\n             isShown_(imageMap.image, ignoreOpacity, parentsDisplayedFn);\n    }\n\n    // Any hidden input is not shown.\n    if ((elemTagName == \"INPUT\") && (elem.type.toLowerCase() == \"hidden\")) {\n      return false;\n    }\n\n    // Any NOSCRIPT element is not shown.\n    if (elemTagName == \"NOSCRIPT\") {\n      return false;\n    }\n\n    // Any element with hidden/collapsed visibility is not shown.\n    var visibility = window.getComputedStyle(elem)[\"visibility\"];\n    if (visibility == \"collapse\" || visibility == \"hidden\") {\n      return false;\n    }\n\n    if (!parentsDisplayedFn(elem)) {\n      return false;\n    }\n\n    // Any transparent element is not shown.\n    if (!ignoreOpacity && getOpacity(elem) == 0) {\n      return false;\n    }\n\n    // Any element without positive size dimensions is not shown.\n    function positiveSize(e) {\n      var rect = getClientRect(e);\n      if (rect.height > 0 && rect.width > 0) {\n        return true;\n      }\n\n      // A vertical or horizontal SVG Path element will report zero width or\n      // height but is \"shown\" if it has a positive stroke-width.\n      if ((e.tagName.toUpperCase() == \"PATH\") && (rect.height > 0 || rect.width > 0)) {\n        var strokeWidth = window.getComputedStyle(e)[\"stroke-width\"];\n        return !!strokeWidth && (parseInt(strokeWidth, 10) > 0);\n      }\n\n      // Zero-sized elements should still be considered to have positive size\n      // if they have a child element or text node with positive size, unless\n      // the element has an 'overflow' style of \"hidden\".\n      return window.getComputedStyle(e)[\"overflow\"] != \"hidden\" &&\n        Array.prototype.slice.call(e.childNodes).some(function(n) {\n          return (n.nodeType == Node.TEXT_NODE) ||\n                 ((n.nodeType == Node.ELEMENT_NODE) && positiveSize(n));\n          });\n    }\n\n    if (!positiveSize(elem)) {\n      return false;\n    }\n\n    // Elements that are hidden by overflow are not shown.\n    function hiddenByOverflow(e) {\n      return getOverflowState(e) == OverflowState.HIDDEN &&\n          Array.prototype.slice.call(e.childNodes).every(function(n) {\n            return (n.nodeType != Node.ELEMENT_NODE) || hiddenByOverflow(n) ||\n                   !positiveSize(n);\n          });\n    }\n    return !hiddenByOverflow(elem);\n  }\n\n  function getClientRegion(elem) {\n    var region = getClientRect(elem);\n    return { left: region.left,\n             right: region.left + region.width,\n             top: region.top,\n             bottom: region.top + region.height };\n  }\n\n  function getParentElement(node) {\n    return node.parentElement\n  }\n\n  function getOverflowState(elem) {\n    var region = getClientRegion(elem);\n    var ownerDoc = elem.ownerDocument;\n    var htmlElem = ownerDoc.documentElement;\n    var bodyElem = ownerDoc.body;\n    var htmlOverflowStyle = window.getComputedStyle(htmlElem)[\"overflow\"];\n    var treatAsFixedPosition;\n\n    // Return the closest ancestor that the given element may overflow.\n    function getOverflowParent(e) {\n      function canBeOverflowed(container) {\n        // The HTML element can always be overflowed.\n        if (container == htmlElem) {\n          return true;\n        }\n        var containerStyle = window.getComputedStyle(container);\n        // An element cannot overflow an element with an inline or contents display style.\n        var containerDisplay = containerStyle[\"display\"];\n        if ((containerDisplay.indexOf(\"inline\") == 0) ||\n            (containerDisplay == \"contents\")) {\n          return false;\n        }\n        // An absolute-positioned element cannot overflow a static-positioned one.\n        if ((position == \"absolute\") && (containerStyle[\"position\"] == \"static\")) {\n          return false;\n        }\n        return true;\n      }\n\n      var position = window.getComputedStyle(e)[\"position\"];\n      if (position == \"fixed\") {\n        treatAsFixedPosition = true;\n        // Fixed-position element may only overflow the viewport.\n        return e == htmlElem ? null : htmlElem;\n      } else {\n        var parent = getParentElement(e);\n        while (parent && !canBeOverflowed(parent)) {\n          parent = getParentElement(parent);\n        }\n        return parent;\n      }\n    };\n\n    // Return the x and y overflow styles for the given element.\n    function getOverflowStyles(e) {\n      // When the <html> element has an overflow style of 'visible', it assumes\n      // the overflow style of the body, and the body is really overflow:visible.\n      var overflowElem = e;\n      if (htmlOverflowStyle == \"visible\") {\n        // NOTE: bodyElem will be null/undefined in SVG documents.\n        if (e == htmlElem && bodyElem) {\n          overflowElem = bodyElem;\n        } else if (e == bodyElem) {\n          return {x: \"visible\", y: \"visible\"};\n        }\n      }\n      var overflowElemStyle = window.getComputedStyle(overflowElem);\n      var overflow = {\n        x: overflowElemStyle[\"overflow-x\"],\n        y: overflowElemStyle[\"overflow-y\"]\n      };\n      // The <html> element cannot have a genuine 'visible' overflow style,\n      // because the viewport can't expand; 'visible' is really 'auto'.\n      if (e == htmlElem) {\n        overflow.x = overflow.x == \"visible\" ? \"auto\" : overflow.x;\n        overflow.y = overflow.y == \"visible\" ? \"auto\" : overflow.y;\n      }\n      return overflow;\n    };\n\n    // Returns the scroll offset of the given element.\n    function getScroll(e) {\n      if (e == htmlElem) {\n        return { x: window.scrollX, y: window.scrollY }\n      }\n      return { x: e.scrollLeft, y: e.scrollTop }\n    }\n\n    // Check if the element overflows any ancestor element.\n    for (var container = getOverflowParent(elem);\n         !!container;\n         container = getOverflowParent(container)) {\n      var containerOverflow = getOverflowStyles(container);\n\n      // If the container has overflow:visible, the element cannot overflow it.\n      if (containerOverflow.x == \"visible\" && containerOverflow.y == \"visible\") {\n        continue;\n      }\n\n      var containerRect = getClientRect(container);\n\n      // Zero-sized containers without overflow:visible hide all descendants.\n      if (containerRect.width == 0 || containerRect.height == 0) {\n        return OverflowState.HIDDEN;\n      }\n\n      // Check \"underflow\": if an element is to the left or above the container\n      var underflowsX = region.right < containerRect.left;\n      var underflowsY = region.bottom < containerRect.top;\n      if ((underflowsX && containerOverflow.x == \"hidden\") ||\n          (underflowsY && containerOverflow.y == \"hidden\")) {\n        return OverflowState.HIDDEN;\n      } else if ((underflowsX && containerOverflow.x != \"visible\") ||\n                 (underflowsY && containerOverflow.y != \"visible\")) {\n        // When the element is positioned to the left or above a container, we\n        // have to distinguish between the element being completely outside the\n        // container and merely scrolled out of view within the container.\n        var containerScroll = getScroll(container);\n        var unscrollableX = region.right < containerRect.left - containerScroll.x;\n        var unscrollableY = region.bottom < containerRect.top - containerScroll.y;\n        if ((unscrollableX && containerOverflow.x != \"visible\") ||\n            (unscrollableY && containerOverflow.x != \"visible\")) {\n          return OverflowState.HIDDEN;\n        }\n        var containerState = getOverflowState(container);\n        return containerState == OverflowState.HIDDEN ?\n            OverflowState.HIDDEN : OverflowState.SCROLL;\n      }\n\n      // Check \"overflow\": if an element is to the right or below a container\n      var overflowsX = region.left >= containerRect.left + containerRect.width;\n      var overflowsY = region.top >= containerRect.top + containerRect.height;\n      if ((overflowsX && containerOverflow.x == \"hidden\") ||\n          (overflowsY && containerOverflow.y == \"hidden\")) {\n        return OverflowState.HIDDEN;\n      } else if ((overflowsX && containerOverflow.x != \"visible\") ||\n                 (overflowsY && containerOverflow.y != \"visible\")) {\n        // If the element has fixed position and falls outside the scrollable area\n        // of the document, then it is hidden.\n        if (treatAsFixedPosition) {\n          var docScroll = getScroll(container);\n          if ((region.left >= htmlElem.scrollWidth - docScroll.x) ||\n              (region.right >= htmlElem.scrollHeight - docScroll.y)) {\n            return OverflowState.HIDDEN;\n          }\n        }\n        // If the element can be scrolled into view of the parent, it has a scroll\n        // state; unless the parent itself is entirely hidden by overflow, in\n        // which it is also hidden by overflow.\n        var containerState = getOverflowState(container);\n        return containerState == OverflowState.HIDDEN ?\n            OverflowState.HIDDEN : OverflowState.SCROLL;\n      }\n    }\n\n    // Does not overflow any ancestor.\n    return OverflowState.NONE;\n  }\n\n  function getViewportSize(win) {\n    var el = win.document.documentElement;\n    return { width: el.clientWidth, height: el.clientHeight };\n  }\n\n  function rect_(x, y, w, h){\n    return { left: x, top: y, width: w, height: h };\n  }\n\n  function getClientRect(elem) {\n    var imageMap = maybeFindImageMap_(elem);\n    if (imageMap) {\n      return imageMap.rect;\n    } else if (elem.tagName.toUpperCase() == \"HTML\") {\n      // Define the client rect of the <html> element to be the viewport.\n      var doc = elem.ownerDocument;\n      // TODO: Is this too simplified???\n      var viewportSize = getViewportSize(window);\n      return rect_(0, 0, viewportSize.width, viewportSize.height);\n    } else {\n      var nativeRect;\n      try {\n        nativeRect = elem.getBoundingClientRect();\n      } catch (e) {\n        return rect_(0, 0, 0, 0);\n      }\n\n      return rect_(nativeRect.left, nativeRect.top,\n                   nativeRect.right - nativeRect.left, nativeRect.bottom - nativeRect.top);\n    }\n  }\n\n  function getOpacity(elem) {\n    // By default the element is opaque.\n    var elemOpacity = 1;\n\n    var opacityStyle = window.getComputedStyle(elem)[\"opacity\"];\n    if (opacityStyle) {\n      elemOpacity = Number(opacityStyle);\n    }\n\n    // Let's apply the parent opacity to the element.\n    var parentElement = getParentElement(elem);\n    if (parentElement && parentElement.nodeType == Node.ELEMENT_NODE) {\n      elemOpacity = elemOpacity * getOpacity(parentElement);\n    }\n    return elemOpacity;\n  }\n\n  function getAreaRelativeRect_(area) {\n    var shape = area.shape.toLowerCase();\n    var coords = area.coords.split(\",\");\n    if (shape == \"rect\" && coords.length == 4) {\n      var x = coords[0], y = coords[1];\n      return rect_(x, y, coords[2] - x, coords[3] - y);\n    } else if (shape == \"circle\" && coords.length == 3) {\n      var centerX = coords[0], centerY = coords[1], radius = coords[2];\n      return rect_(centerX - radius, centerY - radius, 2 * radius, 2 * radius);\n    } else if (shape == \"poly\" && coords.length > 2) {\n      var minX = coords[0], minY = coords[1], maxX = minX, maxY = minY;\n      for (var i = 2; i + 1 < coords.length; i += 2) {\n        minX = Math.min(minX, coords[i]);\n        maxX = Math.max(maxX, coords[i]);\n        minY = Math.min(minY, coords[i + 1]);\n        maxY = Math.max(maxY, coords[i + 1]);\n      }\n      return rect_(minX, minY, maxX - minX, maxY - minY);\n    }\n    return rect_(0, 0, 0, 0);\n  }\n\n  function maybeFindImageMap_(elem) {\n    // If not a <map> or <area>, return null indicating so.\n    var elemTagName = elem.tagName.toUpperCase();\n    var isMap = elemTagName == \"MAP\";\n    if (!isMap && (elemTagName != \"AREA\")) {\n      return null;\n    }\n\n    // Get the <map> associated with this element, or null if none.\n    var map = isMap ? elem :\n        ((getParentElement(elem).tagName.toUpperCase() == \"MAP\") ?\n            getParentElement(elem) : null);\n\n    var image = null, rect = null;\n    if (map && map.name) {\n      var mapDoc = map.ownerDocument;\n\n      image = mapDoc.querySelector(\"*[usemap='#\" + map.name + \"']\");\n\n      if (image) {\n        rect = getClientRect(image);\n        if (!isMap && elem.shape.toLowerCase() != \"default\") {\n          // Shift and crop the relative area rectangle to the map.\n          var relRect = getAreaRelativeRect_(elem);\n          var relX = Math.min(Math.max(relRect.left, 0), rect.width);\n          var relY = Math.min(Math.max(relRect.top, 0), rect.height);\n          var w = Math.min(relRect.width, rect.width - relX);\n          var h = Math.min(relRect.height, rect.height - relY);\n          rect = rect_(relX + rect.left, relY + rect.top, w, h);\n        }\n      }\n    }\n\n    return {image: image, rect: rect || rect_(0, 0, 0, 0)};\n  }\n\n  function getAncestor(element, matcher) {\n    if (element) {\n      element = getParentElement(element);\n    }\n    while (element) {\n      if (matcher(element)) {\n        return element;\n      }\n      element = getParentElement(element);\n    }\n    // Reached the root of the DOM without a match\n    return null;\n  }\n\n\n  function isElement(node, opt_tagName) {\n    // because we call this with deprecated tags such as SHADOW\n    if (opt_tagName && (typeof opt_tagName !== \"string\")) {\n      opt_tagName = opt_tagName.toString();\n    }\n    return !!node && node.nodeType == Node.ELEMENT_NODE &&\n        (!opt_tagName || node.tagName.toUpperCase() == opt_tagName);\n  }\n\n  function getParentNodeInComposedDom(node) {\n    var /**@type {Node}*/ parent = node.parentNode;\n\n    // Shadow DOM v1\n    if (parent && parent.shadowRoot && node.assignedSlot !== undefined) {\n      // Can be null on purpose, meaning it has no parent as\n      // it hasn't yet been slotted\n      return node.assignedSlot ? node.assignedSlot.parentNode : null;\n    }\n\n    // Shadow DOM V0 (deprecated)\n    if (node.getDestinationInsertionPoints) {\n      var destinations = node.getDestinationInsertionPoints();\n      if (destinations.length > 0) {\n        return destinations[destinations.length - 1];\n      }\n    }\n\n    return parent;\n  }\n\n  return function isShown(elem, opt_ignoreOpacity) {\n    /**\n     * Determines whether an element or its parents have `display: none` set\n     * @param {!Node} e the element\n     * @return {boolean}\n     */\n    function displayed(e) {\n      if (window.getComputedStyle(e)[\"display\"] == \"none\"){\n        return false;\n      }\n\n      if (e.matches('*[popover]')) {\n        try {\n          if (e.matches('*:popover-open')) {\n            return true;\n          } else {\n            return false;\n          }\n        } catch (_e) {}\n      }\n\n      var parent = getParentNodeInComposedDom(e);\n\n      if ((typeof ShadowRoot === \"function\") && (parent instanceof ShadowRoot)) {\n        if (parent.host.shadowRoot !== parent) {\n          // There is a younger shadow root, which will take precedence over\n          // the shadow this element is in, thus this element won't be\n          // displayed.\n          return false;\n        } else {\n          parent = parent.host;\n        }\n      }\n\n      if (parent && (parent.nodeType == Node.DOCUMENT_NODE ||\n          parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE)) {\n        return true;\n      }\n\n      // Child of DETAILS element is not shown unless the DETAILS element is open\n      // or the child is a SUMMARY element.\n      if (parent && parent.tagName && (parent.tagName.toUpperCase() == \"DETAILS\") &&\n          !parent.open && !(e.tagName == \"SUMMARY\")) {\n        return false;\n      }\n\n      return parent && displayed(parent);\n    }\n\n    return isShown_(elem, !!opt_ignoreOpacity, displayed);\n  };\n})()\n"
  },
  {
    "path": "lib/capybara/selenium/driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'uri'\nrequire 'English'\n\nclass Capybara::Selenium::Driver < Capybara::Driver::Base\n  include Capybara::Selenium::Find\n\n  DEFAULT_OPTIONS = {\n    browser: :firefox,\n    clear_local_storage: nil,\n    clear_session_storage: nil\n  }.freeze\n  SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout native_displayed].freeze\n  CAPS_VERSION = Gem::Requirement.new('< 4.8.0')\n\n  attr_reader :app, :options\n\n  class << self\n    attr_reader :selenium_webdriver_version\n\n    def load_selenium\n      require 'selenium-webdriver'\n      require 'capybara/selenium/patches/atoms'\n      require 'capybara/selenium/patches/is_displayed'\n\n      # Look up the version of `selenium-webdriver` to\n      # see if it's a version we support.\n      #\n      # By default, we use Gem.loaded_specs to determine\n      # the version number. However, in some cases, such\n      # as when loading `selenium-webdriver` outside of\n      # Rubygems, we fall back to referencing\n      # Selenium::WebDriver::VERSION. Ideally we'd\n      # use the constant in all cases, but earlier versions\n      # of `selenium-webdriver` didn't provide the constant.\n      @selenium_webdriver_version =\n        if Gem.loaded_specs['selenium-webdriver']\n          Gem.loaded_specs['selenium-webdriver'].version\n        else\n          Gem::Version.new(Selenium::WebDriver::VERSION)\n        end\n\n      unless Gem::Requirement.new('>= 4.8').satisfied_by? @selenium_webdriver_version\n        warn \"Warning: You're using an unsupported version of selenium-webdriver, please upgrade to 4.8+.\"\n      end\n\n      @selenium_webdriver_version\n    rescue LoadError => e\n      raise e unless e.message.include?('selenium-webdriver')\n\n      raise LoadError, \"Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler.\"\n    end\n\n    attr_reader :specializations\n\n    def register_specialization(browser_name, specialization)\n      @specializations ||= {}\n      @specializations[browser_name] = specialization\n    end\n  end\n\n  def browser\n    unless @browser\n      options[:http_client] ||= begin\n        require 'capybara/selenium/patches/persistent_client'\n        if options[:timeout]\n          ::Capybara::Selenium::PersistentClient.new(read_timeout: options[:timeout])\n        else\n          ::Capybara::Selenium::PersistentClient.new\n        end\n      end\n      processed_options = options.except(*SPECIAL_OPTIONS)\n\n      @browser = Selenium::WebDriver.for(options[:browser], processed_options)\n\n      specialize_driver\n      setup_exit_handler\n    end\n    @browser\n  end\n\n  def initialize(app, **options)\n    super()\n    self.class.load_selenium\n    @app = app\n    @browser = nil\n    @exit_status = nil\n    @frame_handles = Hash.new { |hash, handle| hash[handle] = [] }\n    @options = DEFAULT_OPTIONS.merge(options)\n    @node_class = ::Capybara::Selenium::Node\n  end\n\n  def visit(path)\n    browser.navigate.to(path)\n  end\n\n  def refresh\n    browser.navigate.refresh\n  end\n\n  def go_back\n    browser.navigate.back\n  end\n\n  def go_forward\n    browser.navigate.forward\n  end\n\n  def html\n    browser.page_source\n  rescue Selenium::WebDriver::Error::JavascriptError => e\n    raise unless e.message.include?('documentElement is null')\n  end\n\n  def title\n    browser.title\n  end\n\n  def current_url\n    browser.current_url\n  end\n\n  def wait?; true; end\n  def needs_server?; true; end\n\n  def execute_script(script, *args)\n    browser.execute_script(script, *native_args(args))\n  end\n\n  def evaluate_script(script, *args)\n    result = execute_script(\"return #{script}\", *args)\n    unwrap_script_result(result)\n  end\n\n  def evaluate_async_script(script, *args)\n    browser.manage.timeouts.script_timeout = Capybara.default_max_wait_time\n    result = browser.execute_async_script(script, *native_args(args))\n    unwrap_script_result(result)\n  end\n\n  def active_element\n    build_node(native_active_element)\n  end\n\n  def send_keys(*args)\n    # Should this call the specialized nodes rather than native???\n    native_active_element.send_keys(*args)\n  end\n\n  def save_screenshot(path, **options)\n    browser.save_screenshot(path, **options)\n  end\n\n  def reset!\n    # Use instance variable directly so we avoid starting the browser just to reset the session\n    return unless @browser\n\n    navigated = false\n    timer = Capybara::Helpers.timer(expire_in: 10)\n    begin\n      # Only trigger a navigation if we haven't done it already, otherwise it\n      # can trigger an endless series of unload modals\n      reset_browser_state unless navigated\n      navigated = true\n      # Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload\n      wait_for_empty_page(timer)\n    rescue *unhandled_alert_errors\n      # This error is thrown if an unhandled alert is on the page\n      # Firefox appears to automatically dismiss this alert, chrome does not\n      # We'll try to accept it\n      accept_unhandled_reset_alert\n      # try cleaning up the browser again\n      retry\n    end\n  end\n\n  def frame_obscured_at?(x:, y:)\n    frame = @frame_handles[current_window_handle].last\n    return false unless frame\n\n    switch_to_frame(:parent)\n    begin\n      frame.base.obscured?(x: x, y: y)\n    ensure\n      switch_to_frame(frame)\n    end\n  end\n\n  def switch_to_frame(frame)\n    handles = @frame_handles[current_window_handle]\n    case frame\n    when :top\n      handles.clear\n      browser.switch_to.default_content\n    when :parent\n      handles.pop\n      browser.switch_to.parent_frame\n    else\n      handles << frame\n      browser.switch_to.frame(frame.native)\n    end\n  end\n\n  def current_window_handle\n    browser.window_handle\n  end\n\n  def window_size(handle)\n    within_given_window(handle) do\n      size = browser.manage.window.size\n      [size.width, size.height]\n    end\n  end\n\n  def resize_window_to(handle, width, height)\n    within_given_window(handle) do\n      browser.manage.window.resize_to(width, height)\n    end\n  end\n\n  def maximize_window(handle)\n    within_given_window(handle) do\n      browser.manage.window.maximize\n    end\n    sleep 0.1 # work around for https://code.google.com/p/selenium/issues/detail?id=7405\n  end\n\n  def fullscreen_window(handle)\n    within_given_window(handle) do\n      browser.manage.window.full_screen\n    end\n  end\n\n  def close_window(handle)\n    raise ArgumentError, 'Not allowed to close the primary window' if handle == window_handles.first\n\n    within_given_window(handle) do\n      browser.close\n    end\n  end\n\n  def window_handles\n    browser.window_handles\n  end\n\n  def open_new_window(kind = :tab)\n    if browser.switch_to.respond_to?(:new_window)\n      handle = current_window_handle\n      browser.switch_to.new_window(kind)\n      switch_to_window(handle)\n    else\n      browser.manage.new_window(kind)\n    end\n  rescue NoMethodError, Selenium::WebDriver::Error::WebDriverError\n    # If not supported by the driver or browser default to using JS\n    browser.execute_script('window.open();')\n  end\n\n  def switch_to_window(handle)\n    browser.switch_to.window handle\n  end\n\n  def accept_modal(_type, **options)\n    yield if block_given?\n    modal = find_modal(**options)\n\n    modal.send_keys options[:with] if options[:with]\n\n    message = modal.text\n    modal.accept\n    message\n  end\n\n  def dismiss_modal(_type, **options)\n    yield if block_given?\n    modal = find_modal(**options)\n    message = modal.text\n    modal.dismiss\n    message\n  end\n\n  def quit\n    @browser&.quit\n  rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED,\n         Selenium::WebDriver::Error::InvalidSessionIdError\n    # Browser must have already gone\n  rescue Selenium::WebDriver::Error::UnknownError => e\n    unless silenced_unknown_error_message?(e.message) # Most likely already gone\n      # probably already gone but not sure - so warn\n      warn \"Ignoring Selenium UnknownError during driver quit: #{e.message}\"\n    end\n  ensure\n    @browser = nil\n  end\n\n  def invalid_element_errors\n    @invalid_element_errors ||=\n      [\n        ::Selenium::WebDriver::Error::StaleElementReferenceError,\n        ::Selenium::WebDriver::Error::ElementNotInteractableError,\n        ::Selenium::WebDriver::Error::InvalidSelectorError, # Work around chromedriver go_back/go_forward race condition\n        ::Selenium::WebDriver::Error::ElementClickInterceptedError,\n        ::Selenium::WebDriver::Error::NoSuchElementError, # IE\n        ::Selenium::WebDriver::Error::InvalidArgumentError # IE\n      ].tap do |errors|\n        if defined?(::Selenium::WebDriver::Error::DetachedShadowRootError)\n          errors.push(::Selenium::WebDriver::Error::DetachedShadowRootError)\n        end\n      end\n  end\n\n  def no_such_window_error\n    Selenium::WebDriver::Error::NoSuchWindowError\n  end\n\nprivate\n\n  def native_args(args)\n    args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg }\n  end\n\n  def native_active_element\n    browser.switch_to.active_element\n  end\n\n  def clear_browser_state\n    delete_all_cookies\n    clear_storage\n  rescue *clear_browser_state_errors\n    # delete_all_cookies fails when we've previously gone\n    # to about:blank, so we rescue this error and do nothing\n    # instead.\n  end\n\n  def clear_browser_state_errors\n    @clear_browser_state_errors ||= [Selenium::WebDriver::Error::UnknownError]\n  end\n\n  def unhandled_alert_errors\n    @unhandled_alert_errors ||= [Selenium::WebDriver::Error::UnexpectedAlertOpenError]\n  end\n\n  def delete_all_cookies\n    @browser.manage.delete_all_cookies\n  end\n\n  def clear_storage\n    clear_session_storage unless options[:clear_session_storage] == false\n    clear_local_storage unless options[:clear_local_storage] == false\n  rescue Selenium::WebDriver::Error::JavascriptError, Selenium::WebDriver::Error::WebDriverError\n    # session/local storage may not be available if on non-http pages (e.g. about:blank)\n  end\n\n  def clear_session_storage\n    if @browser.respond_to? :session_storage\n      @browser.session_storage.clear\n    else\n      begin\n        @browser&.execute_script('window.sessionStorage.clear()')\n      rescue # rubocop:disable Style/RescueStandardError\n        unless options[:clear_session_storage].nil?\n          warn 'sessionStorage clear requested but is not supported by this driver'\n        end\n      end\n    end\n  end\n\n  def clear_local_storage\n    # selenium-webdriver 4.30.0 removed HTML5 storage accessors -- not really sure why\n    # can we replicate this robustly via CDP?\n    if @browser.respond_to? :local_storage\n      @browser.local_storage.clear\n    else\n      begin\n        @browser&.execute_script('window.localStorage.clear()')\n      rescue # rubocop:disable Style/RescueStandardError\n        unless options[:clear_local_storage].nil?\n          warn 'localStorage clear requested but is not supported by this driver'\n        end\n      end\n    end\n  end\n\n  def navigate_with_accept(url)\n    @browser.navigate.to(url)\n    sleep 0.1 # slight wait for alert\n    @browser.switch_to.alert.accept\n  rescue modal_error\n    # alert now gone, should mean navigation happened\n  end\n\n  def modal_error\n    Selenium::WebDriver::Error::NoSuchAlertError\n  end\n\n  def within_given_window(handle)\n    original_handle = current_window_handle\n    if handle == original_handle\n      yield\n    else\n      switch_to_window(handle)\n      result = yield\n      switch_to_window(original_handle)\n      result\n    end\n  end\n\n  def find_modal(text: nil, **options)\n    # Selenium has its own built in wait (2 seconds)for a modal to show up, so this wait is really the minimum time\n    # Actual wait time may be longer than specified\n    wait = Selenium::WebDriver::Wait.new(\n      timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0,\n      ignore: modal_error\n    )\n    begin\n      wait.until do\n        alert = @browser.switch_to.alert\n        regexp = text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(text.to_s))\n        matched = alert.text.match?(regexp)\n        unless matched\n          raise Capybara::ModalNotFound, \"Unable to find modal dialog with #{text} - found '#{alert.text}' instead.\"\n        end\n\n        alert\n      end\n    rescue *find_modal_errors\n      raise Capybara::ModalNotFound, \"Unable to find modal dialog#{\" with #{text}\" if text}\"\n    end\n  end\n\n  def find_modal_errors\n    @find_modal_errors ||= [Selenium::WebDriver::Error::TimeoutError]\n  end\n\n  def silenced_unknown_error_message?(msg)\n    silenced_unknown_error_messages.any? { |regex| msg.match? regex }\n  end\n\n  def silenced_unknown_error_messages\n    [/Error communicating with the remote browser/]\n  end\n\n  def unwrap_script_result(arg)\n    case arg\n    when Array\n      arg.map { |arr| unwrap_script_result(arr) }\n    when Hash\n      arg.transform_values! { |value| unwrap_script_result(value) }\n    when Selenium::WebDriver::Element, Selenium::WebDriver::ShadowRoot\n      build_node(arg)\n    else\n      arg\n    end\n  end\n\n  def find_context\n    browser\n  end\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::Node.new(self, native_node, initial_cache)\n  end\n\n  def bridge\n    browser.send(:bridge)\n  end\n\n  def specialize_driver\n    browser_type = browser.browser\n    Capybara::Selenium::Driver.specializations.select { |k, _v| k === browser_type }.each_value do |specialization| # rubocop:disable Style/CaseEquality\n      extend specialization\n    end\n  end\n\n  def setup_exit_handler\n    main = Process.pid\n    at_exit do\n      # Store the exit status of the test run since it goes away after calling the at_exit proc...\n      @exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)\n      quit if Process.pid == main\n      exit @exit_status if @exit_status # Force exit with stored status\n    end\n  end\n\n  def reset_browser_state\n    clear_browser_state\n    @browser.navigate.to('about:blank')\n  end\n\n  def wait_for_empty_page(timer)\n    until find_xpath('/html/body/*').empty?\n      raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if timer.expired?\n\n      sleep 0.01\n\n      # It has been observed that it is possible that asynchronous JS code in\n      # the application under test can navigate the browser away from about:blank\n      # if the timing is just right. Ensure we are still at about:blank...\n      @browser.navigate.to('about:blank') unless current_url == 'about:blank'\n    end\n  end\n\n  def accept_unhandled_reset_alert\n    @browser.switch_to.alert.accept\n    sleep 0.25 # allow time for the modal to be handled\n  rescue modal_error\n    # The alert is now gone.\n    # If navigation has not occurred attempt again and accept alert\n    # since FF may have dismissed the alert at first attempt.\n    navigate_with_accept('about:blank') if current_url != 'about:blank'\n  end\nend\n\nrequire 'capybara/selenium/driver_specializations/chrome_driver'\nrequire 'capybara/selenium/driver_specializations/firefox_driver'\nrequire 'capybara/selenium/driver_specializations/internet_explorer_driver'\nrequire 'capybara/selenium/driver_specializations/safari_driver'\nrequire 'capybara/selenium/driver_specializations/edge_driver'\n"
  },
  {
    "path": "lib/capybara/selenium/driver_specializations/chrome_driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/nodes/chrome_node'\nrequire 'capybara/selenium/patches/logs'\n\nmodule Capybara::Selenium::Driver::ChromeDriver\n  def self.extended(base)\n    bridge = base.send(:bridge)\n    bridge.extend Capybara::Selenium::ChromeLogs unless bridge.respond_to?(:log)\n    bridge.extend Capybara::Selenium::IsDisplayed unless bridge.send(:commands, :is_element_displayed)\n    base.options[:native_displayed] = false if base.options[:native_displayed].nil?\n  end\n\n  def fullscreen_window(handle)\n    within_given_window(handle) do\n      super\n    rescue NoMethodError => e\n      raise unless e.message.include?('full_screen_window')\n\n      result = bridge.http.call(:post, \"session/#{bridge.session_id}/window/fullscreen\", {})\n      result['value']\n    end\n  end\n\n  def resize_window_to(handle, width, height)\n    super\n  rescue Selenium::WebDriver::Error::UnknownError => e\n    raise unless e.message.include?('failed to change window state')\n\n    # Chromedriver doesn't wait long enough for state to change when coming out of fullscreen\n    # and raises unnecessary error. Wait a bit and try again.\n    sleep 0.25\n    super\n  end\n\n  def reset!\n    # Use instance variable directly so we avoid starting the browser just to reset the session\n    return unless @browser\n\n    switch_to_window(window_handles.first)\n    window_handles.slice(1..).each { |win| close_window(win) }\n    return super if chromedriver_version < 73\n\n    timer = Capybara::Helpers.timer(expire_in: 10)\n    begin\n      clear_storage unless uniform_storage_clear?\n      @browser.navigate.to('about:blank')\n      wait_for_empty_page(timer)\n    rescue *unhandled_alert_errors\n      accept_unhandled_reset_alert\n      retry\n    end\n\n    execute_cdp('Storage.clearDataForOrigin', origin: '*', storageTypes: storage_types_to_clear)\n  end\n\nprivate\n\n  def storage_types_to_clear\n    types = ['cookies']\n    types << 'local_storage' if clear_all_storage?\n    types.join(',')\n  end\n\n  def clear_all_storage?\n    storage_clears.none? false\n  end\n\n  def uniform_storage_clear?\n    storage_clears.uniq { |s| s == false }.length <= 1\n  end\n\n  def storage_clears\n    options.values_at(:clear_session_storage, :clear_local_storage)\n  end\n\n  def clear_storage\n    # Chrome errors if attempt to clear storage on about:blank\n    # In W3C mode it crashes chromedriver\n    url = current_url\n    super unless url.nil? || url.start_with?('about:')\n  end\n\n  def delete_all_cookies\n    execute_cdp('Network.clearBrowserCookies')\n  rescue *cdp_unsupported_errors\n    # If the CDP clear isn't supported do original limited clear\n    super\n  end\n\n  def cdp_unsupported_errors\n    @cdp_unsupported_errors ||= [Selenium::WebDriver::Error::WebDriverError]\n  end\n\n  def execute_cdp(cmd, params = {})\n    if browser.respond_to? :execute_cdp\n      browser.execute_cdp(cmd, **params)\n    else\n      args = { cmd: cmd, params: params }\n      result = bridge.http.call(:post, \"session/#{bridge.session_id}/goog/cdp/execute\", args)\n      result['value']\n    end\n  end\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::ChromeNode.new(self, native_node, initial_cache)\n  end\n\n  def chromedriver_version\n    @chromedriver_version ||= begin\n      caps = browser.capabilities\n      caps['chrome']&.fetch('chromedriverVersion', nil).to_f\n    end\n  end\nend\n\nCapybara::Selenium::Driver.register_specialization :chrome, Capybara::Selenium::Driver::ChromeDriver\n"
  },
  {
    "path": "lib/capybara/selenium/driver_specializations/edge_driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/nodes/edge_node'\n\nmodule Capybara::Selenium::Driver::EdgeDriver\n  def self.extended(base)\n    bridge = base.send(:bridge)\n    bridge.extend Capybara::Selenium::IsDisplayed unless bridge.send(:commands, :is_element_displayed)\n    base.options[:native_displayed] = false if base.options[:native_displayed].nil?\n  end\n\n  def fullscreen_window(handle)\n    return super if edgedriver_version < 75\n\n    within_given_window(handle) do\n      super\n    rescue NoMethodError => e\n      raise unless e.message.include?('full_screen_window')\n\n      result = bridge.http.call(:post, \"session/#{bridge.session_id}/window/fullscreen\", {})\n      result['value']\n    end\n  end\n\n  def resize_window_to(handle, width, height)\n    super\n  rescue Selenium::WebDriver::Error::UnknownError => e\n    raise unless e.message.include?('failed to change window state')\n\n    # Chromedriver doesn't wait long enough for state to change when coming out of fullscreen\n    # and raises unnecessary error. Wait a bit and try again.\n    sleep 0.25\n    super\n  end\n\n  def reset!\n    return super if edgedriver_version < 75\n    # Use instance variable directly so we avoid starting the browser just to reset the session\n    return unless @browser\n\n    switch_to_window(window_handles.first)\n    window_handles.slice(1..).each { |win| close_window(win) }\n\n    timer = Capybara::Helpers.timer(expire_in: 10)\n    begin\n      clear_storage unless uniform_storage_clear?\n      @browser.navigate.to('about:blank')\n      wait_for_empty_page(timer)\n    rescue *unhandled_alert_errors\n      accept_unhandled_reset_alert\n      retry\n    end\n\n    execute_cdp('Storage.clearDataForOrigin', origin: '*', storageTypes: storage_types_to_clear)\n  end\n\n  def download_path=(path)\n    if @browser.respond_to?(:download_path=)\n      @browser.download_path = path\n    else\n      # Not yet implemented in seleniun-webdriver for edge so do it ourselves\n      execute_cdp('Page.setDownloadBehavior', behavior: 'allow', downloadPath: path)\n    end\n  end\n\nprivate\n\n  def storage_types_to_clear\n    types = ['cookies']\n    types << 'local_storage' if clear_all_storage?\n    types.join(',')\n  end\n\n  def clear_all_storage?\n    storage_clears.none? false\n  end\n\n  def uniform_storage_clear?\n    storage_clears.uniq { |s| s == false }.length <= 1\n  end\n\n  def storage_clears\n    options.values_at(:clear_session_storage, :clear_local_storage)\n  end\n\n  def clear_storage\n    # Edgedriver crashes if attempt to clear storage on about:blank\n    url = current_url\n    super unless url.nil? || url.start_with?('about:')\n  end\n\n  def delete_all_cookies\n    return super if edgedriver_version < 75\n\n    execute_cdp('Network.clearBrowserCookies')\n  rescue *cdp_unsupported_errors\n    # If the CDP clear isn't supported do original limited clear\n    super\n  end\n\n  def cdp_unsupported_errors\n    @cdp_unsupported_errors ||= [Selenium::WebDriver::Error::WebDriverError]\n  end\n\n  def execute_cdp(cmd, params = {})\n    if browser.respond_to? :execute_cdp\n      browser.execute_cdp(cmd, **params)\n    else\n      args = { cmd: cmd, params: params }\n      result = bridge.http.call(:post, \"session/#{bridge.session_id}/ms/cdp/execute\", args)\n      result['value']\n    end\n  end\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::EdgeNode.new(self, native_node, initial_cache)\n  end\n\n  def edgedriver_version\n    @edgedriver_version ||= begin\n      caps = browser.capabilities\n      caps['msedge']&.fetch('msedgedriverVersion', nil).to_f\n    end\n  end\nend\n\nCapybara::Selenium::Driver.register_specialization :edge, Capybara::Selenium::Driver::EdgeDriver\nCapybara::Selenium::Driver.register_specialization :edge_chrome, Capybara::Selenium::Driver::EdgeDriver\n"
  },
  {
    "path": "lib/capybara/selenium/driver_specializations/firefox_driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/nodes/firefox_node'\n\nmodule Capybara::Selenium::Driver::FirefoxDriver\n  def self.extended(driver)\n    driver.extend Capybara::Selenium::Driver::W3CFirefoxDriver\n    bridge = driver.send(:bridge)\n    bridge.extend Capybara::Selenium::IsDisplayed unless bridge.send(:commands, :is_element_displayed)\n  end\nend\n\nmodule Capybara::Selenium::Driver::W3CFirefoxDriver\n  class << self\n    def extended(driver)\n      require 'capybara/selenium/patches/pause_duration_fix' if pause_broken?(driver.browser)\n      driver.options[:native_displayed] = false if driver.options[:native_displayed].nil?\n    end\n\n    def pause_broken?(sel_driver)\n      sel_driver.capabilities['moz:geckodriverVersion']&.start_with?('0.22.')\n    end\n  end\n\n  def resize_window_to(handle, width, height)\n    within_given_window(handle) do\n      # Don't set the size if already set - See https://github.com/mozilla/geckodriver/issues/643\n      if window_size(handle) == [width, height]\n        {}\n      else\n        super\n      end\n    end\n  end\n\n  def reset!\n    # Use instance variable directly so we avoid starting the browser just to reset the session\n    return unless @browser\n\n    if browser_version >= 68\n      begin\n        # Firefox 68 hangs if we try to switch windows while a modal is visible\n        browser.switch_to.alert&.dismiss\n      rescue Selenium::WebDriver::Error::NoSuchAlertError\n        # Swallow\n      end\n    end\n\n    switch_to_window(window_handles.first)\n    window_handles.slice(1..).each { |win| close_window(win) }\n    super\n  end\n\n  def refresh\n    # Accept any \"will repost content\" confirmation that occurs\n    accept_modal :confirm, wait: 0.1 do\n      super\n    end\n  rescue Capybara::ModalNotFound\n    # No modal was opened - page has refreshed - ignore\n  end\n\n  def switch_to_frame(frame)\n    return super unless frame == :parent\n\n    # geckodriver/firefox has an issue if the current frame is removed from within it\n    # so we have to move to the default_content and iterate back through the frames\n    handles = @frame_handles[current_window_handle]\n    browser.switch_to.default_content\n    handles.tap(&:pop).each { |fh| browser.switch_to.frame(fh.native) }\n  end\n\nprivate\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::FirefoxNode.new(self, native_node, initial_cache)\n  end\n\n  def browser_version\n    browser.capabilities[:browser_version].to_f\n  end\nend\n\nCapybara::Selenium::Driver.register_specialization :firefox, Capybara::Selenium::Driver::FirefoxDriver\n"
  },
  {
    "path": "lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/nodes/ie_node'\n\nmodule Capybara::Selenium::Driver::InternetExplorerDriver\n  def switch_to_frame(frame)\n    return super unless frame == :parent\n\n    # iedriverserver has an issue if the current frame is removed from within it\n    # so we have to move to the default_content and iterate back through the frames\n    handles = @frame_handles[current_window_handle]\n    browser.switch_to.default_content\n    handles.tap(&:pop).each { |fh| browser.switch_to.frame(fh.native) }\n  end\n\nprivate\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::IENode.new(self, native_node, initial_cache)\n  end\nend\n\nmodule Capybara::Selenium\n  Driver.register_specialization :ie, Driver::InternetExplorerDriver\n  Driver.register_specialization :internet_explorer, Driver::InternetExplorerDriver\nend\n"
  },
  {
    "path": "lib/capybara/selenium/driver_specializations/safari_driver.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/nodes/safari_node'\n\nmodule Capybara::Selenium::Driver::SafariDriver\n  def switch_to_frame(frame)\n    return super unless frame == :parent\n\n    # safaridriver/safari has an issue where switch_to_frame(:parent)\n    # behaves like switch_to_frame(:top)\n    handles = @frame_handles[current_window_handle]\n    browser.switch_to.default_content\n    handles.tap(&:pop).each { |fh| browser.switch_to.frame(fh.native) }\n  end\n\nprivate\n\n  def build_node(native_node, initial_cache = {})\n    ::Capybara::Selenium::SafariNode.new(self, native_node, initial_cache)\n  end\nend\n\nCapybara::Selenium::Driver.register_specialization(/^(safari|Safari_Technology_Preview)$/,\n                                                   Capybara::Selenium::Driver::SafariDriver)\n"
  },
  {
    "path": "lib/capybara/selenium/extensions/file_input_click_emulation.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::Selenium::Node\n  module FileInputClickEmulation\n    def click(keys = [], **options)\n      super\n    rescue Selenium::WebDriver::Error::InvalidArgumentError\n      return emulate_click if attaching_file? && visible_file_field?\n\n      raise\n    end\n\n  private\n\n    def visible_file_field?\n      (attrs(:tagName, :type).map { |val| val&.downcase } == %w[input file]) && visible?\n    end\n\n    def attaching_file?\n      caller_locations.any? { |cl| cl.base_label == 'attach_file' }\n    end\n\n    def emulate_click\n      driver.execute_script(<<~JS, self)\n        arguments[0].dispatchEvent(\n          new MouseEvent('click', {\n            view: window,\n            bubbles: true,\n            cancelable: true\n          }));\n      JS\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/extensions/find.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Selenium\n    module Find\n      def find_xpath(selector, uses_visibility: false, styles: nil, position: false, **_options)\n        find_by(:xpath, selector, uses_visibility: uses_visibility, texts: [], styles: styles, position: position)\n      end\n\n      def find_css(selector, uses_visibility: false, texts: [], styles: nil, position: false, **_options)\n        find_by(:css, selector, uses_visibility: uses_visibility, texts: texts, styles: styles, position: position)\n      end\n\n    private\n\n      def find_by(format, selector, uses_visibility:, texts:, styles:, position:)\n        els = find_context.find_elements(format, selector)\n        hints = []\n\n        if (els.size > 2) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']\n          els = filter_by_text(els, texts) unless texts.empty?\n          hints = begin\n            gather_hints(els, uses_visibility: uses_visibility, styles: styles, position: position)\n          rescue Selenium::WebDriver::Error::JavascriptError\n            # Unclear how this can happen but issue #2729 indicates it can\n            []\n          end\n        end\n        els.map.with_index { |el, idx| build_node(el, hints[idx] || {}) }\n      end\n\n      def gather_hints(elements, uses_visibility:, styles:, position:)\n        hints_js, functions = build_hints_js(uses_visibility, styles, position)\n        return [] unless functions.any?\n\n        (es_context.execute_script(hints_js, elements) || []).map! do |results|\n          hint = {}\n          hint[:style] = results.pop if functions.include?(:style_func)\n          hint[:position] = results.pop if functions.include?(:position_func)\n          hint[:visible] = results.pop if functions.include?(:vis_func)\n          hint\n        end\n      rescue ::Selenium::WebDriver::Error::StaleElementReferenceError,\n             ::Capybara::NotSupportedByDriverError\n        # warn 'Unexpected Stale Element Error - skipping optimization'\n        []\n      end\n\n      def filter_by_text(elements, texts)\n        es_context.execute_script <<~JS, elements, texts\n          var texts = arguments[1];\n          return arguments[0].filter(function(el){\n            var content = el.textContent.toLowerCase();\n            return texts.every(function(txt){ return content.indexOf(txt.toLowerCase()) != -1 });\n          })\n        JS\n      end\n\n      def build_hints_js(uses_visibility, styles, position)\n        functions = []\n        hints_js = +''\n\n        if uses_visibility && !is_displayed_atom.empty?\n          hints_js << <<~VISIBILITY_JS\n            var vis_func = #{is_displayed_atom};\n          VISIBILITY_JS\n          functions << :vis_func\n        end\n\n        if position\n          hints_js << <<~POSITION_JS\n            var position_func = function(el){\n              return el.getBoundingClientRect();\n            };\n          POSITION_JS\n          functions << :position_func\n        end\n\n        if styles.is_a? Hash\n          hints_js << <<~STYLE_JS\n            var style_func = function(el){\n              var el_styles = window.getComputedStyle(el);\n              return #{styles.keys.map(&:to_s)}.reduce(function(res, style){\n                res[style] = el_styles[style];\n                return res;\n              }, {});\n            };\n          STYLE_JS\n          functions << :style_func\n        end\n\n        hints_js << <<~EACH_JS\n          return arguments[0].map(function(el){\n            return [#{functions.join(',')}].map(function(fn){ return fn.call(null, el) });\n          });\n        EACH_JS\n\n        [hints_js, functions]\n      end\n\n      def es_context\n        respond_to?(:execute_script) ? self : driver\n      end\n\n      def is_displayed_atom # rubocop:disable Naming/PredicatePrefix\n        @@is_displayed_atom ||= begin # rubocop:disable Style/ClassVars\n          browser.send(:bridge).send(:read_atom, 'isDisplayed')\n        rescue StandardError\n          # If the atom doesn't exist or other error\n          ''\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/extensions/html5_drag.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::Selenium::Node\n  module Html5Drag\n    # Implement methods to emulate HTML5 drag and drop\n\n    def drag_to(element, html5: nil, delay: 0.05, drop_modifiers: [])\n      drop_modifiers = Array(drop_modifiers)\n\n      driver.execute_script MOUSEDOWN_TRACKER\n      scroll_if_needed { browser_action.click_and_hold(native).perform }\n      html5 = !driver.evaluate_script(LEGACY_DRAG_CHECK, self) if html5.nil?\n      if html5\n        perform_html5_drag(element, delay, drop_modifiers)\n      else\n        perform_legacy_drag(element, drop_modifiers)\n      end\n    end\n\n  private\n\n    def perform_legacy_drag(element, drop_modifiers)\n      element.scroll_if_needed do\n        # browser_action.move_to(element.native).release.perform\n        keys_down = modifiers_down(browser_action, drop_modifiers)\n        keys_up = modifiers_up(keys_down.move_to(element.native).release, drop_modifiers)\n        keys_up.perform\n      end\n    end\n\n    def perform_html5_drag(element, delay, drop_modifiers)\n      driver.evaluate_async_script HTML5_DRAG_DROP_SCRIPT, self, element, delay * 1000, normalize_keys(drop_modifiers)\n      browser_action.release.perform\n    end\n\n    def html5_drop(*args)\n      if args[0].is_a? String\n        input = driver.evaluate_script ATTACH_FILE\n        input.set_file(args)\n        driver.execute_script DROP_FILE, self, input\n      else\n        items = args.flat_map do |arg|\n          arg.map { |(type, data)| { type: type, data: data } }\n        end\n        driver.execute_script DROP_STRING, items, self\n      end\n    end\n\n    DROP_STRING = <<~JS\n      var strings = arguments[0],\n          el = arguments[1],\n          dt = new DataTransfer(),\n          opts = { cancelable: true, bubbles: true, dataTransfer: dt };\n      for (var i=0; i < strings.length; i++){\n        if (dt.items) {\n          dt.items.add(strings[i]['data'], strings[i]['type']);\n        } else {\n          dt.setData(strings[i]['type'], strings[i]['data']);\n        }\n      }\n      var dropEvent = new DragEvent('drop', opts);\n      el.dispatchEvent(dropEvent);\n    JS\n\n    DROP_FILE = <<~JS\n      var el = arguments[0],\n          input = arguments[1],\n          files = input.files,\n          dt = new DataTransfer(),\n          opts = { cancelable: true, bubbles: true, dataTransfer: dt };\n      input.parentElement.removeChild(input);\n      if (dt.items){\n        for (var i=0; i<files.length; i++){\n          dt.items.add(files[i]);\n        }\n      } else {\n        Object.defineProperty(dt, \"files\", {\n          value: files,\n          writable: false\n        });\n      }\n      var dropEvent = new DragEvent('drop', opts);\n      el.dispatchEvent(dropEvent);\n    JS\n\n    ATTACH_FILE = <<~JS\n      (function(){\n        var input = document.createElement('INPUT');\n        input.type = \"file\";\n        input.id = \"_capybara_drop_file\";\n        input.multiple = true;\n        document.body.appendChild(input);\n        return input;\n      })()\n    JS\n\n    MOUSEDOWN_TRACKER = <<~JS\n      window.capybara_mousedown_prevented = null;\n      document.addEventListener('mousedown', ev => {\n        window.capybara_mousedown_prevented = ev.defaultPrevented;\n      }, { once: true, passive: true })\n    JS\n\n    LEGACY_DRAG_CHECK = <<~JS\n      (function(el){\n        if ([true, null].indexOf(window.capybara_mousedown_prevented) >= 0){\n          return true;\n        }\n\n        do {\n          if (el.draggable) return false;\n        } while (el = el.parentElement );\n        return true;\n      })(arguments[0])\n    JS\n\n    HTML5_DRAG_DROP_SCRIPT = <<~JS\n      function rectCenter(rect){\n        return new DOMPoint(\n          (rect.left + rect.right)/2,\n          (rect.top + rect.bottom)/2\n        );\n      }\n\n      function pointOnRect(pt, rect) {\n      \tvar rectPt = rectCenter(rect);\n      \tvar slope = (rectPt.y - pt.y) / (rectPt.x - pt.x);\n\n      \tif (pt.x <= rectPt.x) { // left side\n      \t\tvar minXy = slope * (rect.left - pt.x) + pt.y;\n      \t\tif (rect.top <= minXy && minXy <= rect.bottom)\n            return new DOMPoint(rect.left, minXy);\n      \t}\n\n      \tif (pt.x >= rectPt.x) { // right side\n      \t\tvar maxXy = slope * (rect.right - pt.x) + pt.y;\n      \t\tif (rect.top <= maxXy && maxXy <= rect.bottom)\n            return new DOMPoint(rect.right, maxXy);\n      \t}\n\n      \tif (pt.y <= rectPt.y) { // top side\n      \t\tvar minYx = (rectPt.top - pt.y) / slope + pt.x;\n      \t\tif (rect.left <= minYx && minYx <= rect.right)\n            return new DOMPoint(minYx, rect.top);\n      \t}\n\n      \tif (pt.y >= rectPt.y) { // bottom side\n      \t\tvar maxYx = (rect.bottom - pt.y) / slope + pt.x;\n      \t\tif (rect.left <= maxYx && maxYx <= rect.right)\n            return new DOMPoint(maxYx, rect.bottom);\n      \t}\n\n        return new DOMPoint(pt.x,pt.y);\n      }\n\n      function dragEnterTarget() {\n        target.scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});\n        var targetRect = target.getBoundingClientRect();\n        var sourceCenter = rectCenter(source.getBoundingClientRect());\n\n        for (var i = 0; i < drop_modifier_keys.length; i++) {\n          key = drop_modifier_keys[i];\n          if (key == \"control\"){\n            key = \"ctrl\"\n          }\n          opts[key + 'Key'] = true;\n        }\n\n        var dragEnterEvent = new DragEvent('dragenter', opts);\n        target.dispatchEvent(dragEnterEvent);\n\n        // fire 2 dragover events to simulate dragging with a direction\n        var entryPoint = pointOnRect(sourceCenter, targetRect)\n        var dragOverOpts = Object.assign({clientX: entryPoint.x, clientY: entryPoint.y}, opts);\n        var dragOverEvent = new DragEvent('dragover', dragOverOpts);\n        target.dispatchEvent(dragOverEvent);\n        window.setTimeout(dragOnTarget, step_delay);\n      }\n\n      function dragOnTarget() {\n        var targetCenter = rectCenter(target.getBoundingClientRect());\n        var dragOverOpts = Object.assign({clientX: targetCenter.x, clientY: targetCenter.y}, opts);\n        var dragOverEvent = new DragEvent('dragover', dragOverOpts);\n        target.dispatchEvent(dragOverEvent);\n        window.setTimeout(dragLeave, step_delay, dragOverEvent.defaultPrevented, dragOverOpts);\n      }\n\n      function dragLeave(drop, dragOverOpts) {\n        var dragLeaveOptions = Object.assign({}, opts, dragOverOpts);\n        var dragLeaveEvent = new DragEvent('dragleave', dragLeaveOptions);\n        target.dispatchEvent(dragLeaveEvent);\n        if (drop) {\n          var dropEvent = new DragEvent('drop', dragLeaveOptions);\n          target.dispatchEvent(dropEvent);\n        }\n        var dragEndEvent = new DragEvent('dragend', dragLeaveOptions);\n        source.dispatchEvent(dragEndEvent);\n        callback.call(true);\n      }\n\n      var source = arguments[0],\n          target = arguments[1],\n          step_delay = arguments[2],\n          drop_modifier_keys = arguments[3],\n          callback = arguments[4];\n\n      var dt = new DataTransfer();\n      var opts = { cancelable: true, bubbles: true, dataTransfer: dt };\n\n      while (source && !source.draggable) {\n        source = source.parentElement;\n      }\n\n      if (source.tagName == 'A'){\n        dt.setData('text/uri-list', source.href);\n        dt.setData('text', source.href);\n      }\n      if (source.tagName == 'IMG'){\n        dt.setData('text/uri-list', source.src);\n        dt.setData('text', source.src);\n      }\n\n      var dragEvent = new DragEvent('dragstart', opts);\n      source.dispatchEvent(dragEvent);\n\n      window.setTimeout(dragEnterTarget, step_delay);\n    JS\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/extensions/modifier_keys_stack.rb",
    "content": "# frozen_string_literal: true\n\nclass Capybara::Selenium::Node\n  #\n  # @api private\n  #\n  class ModifierKeysStack\n    def initialize\n      @stack = []\n    end\n\n    def include?(key)\n      @stack.flatten.include?(key)\n    end\n\n    def press(key)\n      @stack.last.push(key)\n    end\n\n    def push\n      @stack.push []\n    end\n\n    def pop\n      @stack.pop\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/extensions/scroll.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Selenium\n    module Scroll\n      def scroll_by(x, y)\n        driver.execute_script <<~JS, self, x, y\n          var el = arguments[0];\n          if (el.scrollBy){\n            el.scrollBy(arguments[1], arguments[2]);\n          } else {\n            el.scrollTop = el.scrollTop + arguments[2];\n            el.scrollLeft = el.scrollLeft + arguments[1];\n          }\n        JS\n      end\n\n      def scroll_to(element, location, position = nil)\n        # location, element = element, nil if element.is_a? Symbol\n        if element.is_a? Capybara::Selenium::Node\n          scroll_element_to_location(element, location)\n        elsif location.is_a? Symbol\n          scroll_to_location(location)\n        else\n          scroll_to_coords(*position)\n        end\n        self\n      end\n\n    private\n\n      def scroll_element_to_location(element, location)\n        scroll_opts = case location\n        when :top\n          'true'\n        when :bottom\n          'false'\n        when :center\n          \"{behavior: 'instant', block: 'center'}\"\n        else\n          raise ArgumentError, \"Invalid scroll_to location: #{location}\"\n        end\n        driver.execute_script <<~JS, element\n          arguments[0].scrollIntoView(#{scroll_opts})\n        JS\n      end\n\n      SCROLL_POSITIONS = {\n        top: '0',\n        bottom: 'arguments[0].scrollHeight',\n        center: '(arguments[0].scrollHeight - arguments[0].clientHeight)/2'\n      }.freeze\n\n      def scroll_to_location(location)\n        driver.execute_script <<~JS, self\n          if (arguments[0].scrollTo){\n            arguments[0].scrollTo(0, #{SCROLL_POSITIONS[location]});\n          } else {\n            arguments[0].scrollTop = #{SCROLL_POSITIONS[location]};\n          }\n        JS\n      end\n\n      def scroll_to_coords(x, y)\n        driver.execute_script <<~JS, self, x, y\n          if (arguments[0].scrollTo){\n            arguments[0].scrollTo(arguments[1], arguments[2]);\n          } else {\n            arguments[0].scrollTop = arguments[2];\n            arguments[0].scrollLeft = arguments[1];\n          }\n        JS\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/node.rb",
    "content": "# frozen_string_literal: true\n\n# Selenium specific implementation of the Capybara::Driver::Node API\n\nrequire 'capybara/selenium/extensions/find'\nrequire 'capybara/selenium/extensions/scroll'\nrequire 'capybara/node/whitespace_normalizer'\n\nclass Capybara::Selenium::Node < Capybara::Driver::Node\n  include Capybara::Node::WhitespaceNormalizer\n  include Capybara::Selenium::Find\n  include Capybara::Selenium::Scroll\n\n  def visible_text\n    raise NotImplementedError, 'Getting visible text is not currently supported directly on shadow roots' if shadow_root?\n\n    native.text\n  end\n\n  def all_text\n    text = driver.evaluate_script('arguments[0].textContent', self) || ''\n    normalize_spacing(text)\n  end\n\n  def [](name)\n    native.attribute(name.to_s)\n  rescue Selenium::WebDriver::Error::WebDriverError\n    nil\n  end\n\n  def value\n    if tag_name == 'select' && multiple?\n      native.find_elements(:css, 'option:checked').map { |el| el[:value] || el.text }\n    else\n      native[:value]\n    end\n  end\n\n  def style(styles)\n    styles.to_h { |style| [style, native.css_value(style)] }\n  end\n\n  ##\n  #\n  # Set the value of the form element to the given value.\n  #\n  # @param [String] value    The new value\n  # @param [Hash{}] options  Driver specific options for how to set the value\n  # @option options [Symbol,Array] :clear (nil) The method used to clear the previous value <br/>\n  #   nil => clear via javascript <br/>\n  #   :none =>  append the new value to the existing value <br/>\n  #   :backspace => send backspace keystrokes to clear the field <br/>\n  #   Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]\n  # @option options [Boolean] :rapid (nil) Whether setting text inputs should use a faster &quot;rapid&quot; mode<br/>\n  #   nil => Text inputs with length greater than 30 characters will be set using a faster driver script mode<br/>\n  #   true => Rapid mode will be used regardless of input length<br/>\n  #   false => Sends keys via conventional mode. This may be required to avoid losing key-presses if you have certain\n  #            Javascript interactions on form inputs<br/>\n  def set(value, **options)\n    if value.is_a?(Array) && !multiple?\n      raise ArgumentError, \"Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}\"\n    end\n\n    tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase }\n    @tag_name ||= tag_name\n\n    case tag_name\n    when 'input'\n      case type\n      when 'radio'\n        click\n      when 'checkbox'\n        click if value ^ checked?\n      when 'file'\n        set_file(value)\n      when 'date'\n        set_date(value)\n      when 'time'\n        set_time(value)\n      when 'datetime-local'\n        set_datetime_local(value)\n      when 'color'\n        set_color(value)\n      when 'range'\n        set_range(value)\n      else\n        set_text(value, **options)\n      end\n    when 'textarea'\n      set_text(value, **options)\n    else\n      set_content_editable(value)\n    end\n  end\n\n  def select_option\n    click unless selected? || disabled?\n  end\n\n  def unselect_option\n    raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select_node.multiple?\n\n    click if selected?\n  end\n\n  def click(keys = [], **options)\n    click_options = ClickOptions.new(keys, options)\n    return native.click if click_options.empty?\n\n    perform_with_options(click_options) do |action|\n      target = click_options.coords? ? nil : native\n      if click_options.delay.zero?\n        action.click(target)\n      else\n        action.click_and_hold(target)\n        action_pause(action, click_options.delay)\n        action.release\n      end\n    end\n  rescue StandardError => e\n    if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||\n       e.message.include?('Other element would receive the click')\n      scroll_to_center\n    end\n\n    raise e\n  end\n\n  def right_click(keys = [], **options)\n    click_options = ClickOptions.new(keys, options)\n    perform_with_options(click_options) do |action|\n      target = click_options.coords? ? nil : native\n      if click_options.delay.zero?\n        action.context_click(target)\n      else\n        action.move_to(target) if target\n        action.pointer_down(:right).then do |act|\n          action_pause(act, click_options.delay)\n        end.pointer_up(:right)\n      end\n    end\n  end\n\n  def double_click(keys = [], **options)\n    click_options = ClickOptions.new(keys, options)\n    raise ArgumentError, \"double_click doesn't support a delay option\" unless click_options.delay.zero?\n\n    perform_with_options(click_options) do |action|\n      click_options.coords? ? action.double_click : action.double_click(native)\n    end\n  end\n\n  def send_keys(*args)\n    native.send_keys(*args)\n  end\n\n  def hover\n    scroll_if_needed { browser_action.move_to(native).perform }\n  end\n\n  def drag_to(element, drop_modifiers: [], **)\n    drop_modifiers = Array(drop_modifiers)\n    # Due to W3C spec compliance - The Actions API no longer scrolls to elements when necessary\n    # which means Seleniums `drag_and_drop` is now broken - do it manually\n    scroll_if_needed { browser_action.click_and_hold(native).perform }\n    # element.scroll_if_needed { browser_action.move_to(element.native).release.perform }\n    element.scroll_if_needed do\n      keys_down = modifiers_down(browser_action, drop_modifiers)\n      keys_up = modifiers_up(keys_down.move_to(element.native).release, drop_modifiers)\n      keys_up.perform\n    end\n  end\n\n  def drop(*_)\n    raise NotImplementedError, 'Out of browser drop emulation is not implemented for the current browser'\n  end\n\n  def tag_name\n    @tag_name ||=\n      if native.respond_to? :tag_name\n        native.tag_name.downcase\n      else\n        shadow_root? ? 'ShadowRoot' : 'Unknown'\n      end\n  end\n\n  def visible?; boolean_attr(native.displayed?); end\n  def readonly?; boolean_attr(self[:readonly]); end\n  def multiple?; boolean_attr(self[:multiple]); end\n  def selected?; boolean_attr(native.selected?); end\n  alias :checked? :selected?\n\n  def disabled?\n    return true unless native.enabled?\n\n    # WebDriver only defines `disabled?` for form controls but fieldset makes sense too\n    find_xpath('self::fieldset/ancestor-or-self::fieldset[@disabled]').any?\n  end\n\n  def content_editable?\n    native.attribute('isContentEditable') == 'true'\n  end\n\n  def path\n    driver.evaluate_script GET_XPATH_SCRIPT, self\n  end\n\n  def obscured?(x: nil, y: nil)\n    res = driver.evaluate_script(OBSCURED_OR_OFFSET_SCRIPT, self, x, y)\n    return true if res == true\n\n    driver.frame_obscured_at?(x: res['x'], y: res['y'])\n  end\n\n  def rect\n    native.rect\n  end\n\n  def shadow_root\n    root = native.shadow_root\n    root && build_node(native.shadow_root)\n  end\n\nprotected\n\n  def scroll_if_needed\n    yield\n  rescue ::Selenium::WebDriver::Error::MoveTargetOutOfBoundsError\n    scroll_to_center\n    yield\n  end\n\n  def scroll_to_center\n    script = <<-JS\n      try {\n        arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});\n      } catch(e) {\n        arguments[0].scrollIntoView(true);\n      }\n    JS\n    begin\n      driver.execute_script(script, self)\n    rescue StandardError\n      # Swallow error if scrollIntoView with options isn't supported\n    end\n  end\n\nprivate\n\n  def sibling_index(parent, node, selector)\n    siblings = parent.find_xpath(selector)\n    case siblings.size\n    when 0\n      '[ERROR]' # IE doesn't support full XPath (namespace-uri, etc)\n    when 1\n      '' # index not necessary when only one matching element\n    else\n      idx = siblings.index(node)\n      # Element may not be found in the siblings if it has gone away\n      idx.nil? ? '[ERROR]' : \"[#{idx + 1}]\"\n    end\n  end\n\n  def boolean_attr(val)\n    val && (val != 'false')\n  end\n\n  # a reference to the select node if this is an option node\n  def select_node\n    find_xpath(XPath.ancestor(:select)[1]).first\n  end\n\n  def set_text(value, clear: nil, rapid: nil, **_unused)\n    value = value.to_s\n    if value.empty? && clear.nil?\n      native.clear\n    elsif clear == :backspace\n      # Clear field by sending the correct number of backspace keys.\n      backspaces = [:backspace] * self.value.to_s.length\n      send_keys(:end, *backspaces, value)\n    elsif clear.is_a? Array\n      send_keys(*clear, value)\n    else\n      driver.execute_script 'arguments[0].select()', self unless clear == :none\n      if rapid == true || ((value.length > auto_rapid_set_length) && rapid != false)\n        send_keys(value[0..3])\n        driver.execute_script RAPID_APPEND_TEXT, self, value[4...-3]\n        send_keys(value[-3..])\n      else\n        send_keys(value)\n      end\n    end\n  end\n\n  def auto_rapid_set_length\n    30\n  end\n\n  def perform_with_options(click_options, &block)\n    raise ArgumentError, 'A block must be provided' unless block\n\n    scroll_if_needed do\n      action_with_modifiers(click_options) do |action|\n        if block\n          yield action\n        else\n          click_options.coords? ? action.click : action.click(native)\n        end\n      end\n    end\n  end\n\n  def set_date(value) # rubocop:disable Naming/AccessorMethodName\n    value = SettableValue.new(value)\n    return set_text(value) unless value.dateable?\n\n    # TODO: this would be better if locale can be detected and correct keystrokes sent\n    update_value_js(value.to_date_str)\n  end\n\n  def set_time(value) # rubocop:disable Naming/AccessorMethodName\n    value = SettableValue.new(value)\n    return set_text(value) unless value.timeable?\n\n    # TODO: this would be better if locale can be detected and correct keystrokes sent\n    update_value_js(value.to_time_str)\n  end\n\n  def set_datetime_local(value) # rubocop:disable Naming/AccessorMethodName\n    value = SettableValue.new(value)\n    return set_text(value) unless value.timeable?\n\n    # TODO: this would be better if locale can be detected and correct keystrokes sent\n    update_value_js(value.to_datetime_str)\n  end\n\n  def set_color(value) # rubocop:disable Naming/AccessorMethodName\n    update_value_js(value)\n  end\n\n  def set_range(value) # rubocop:disable Naming/AccessorMethodName\n    update_value_js(value)\n  end\n\n  def update_value_js(value)\n    driver.execute_script(<<-JS, self, value)\n      if (arguments[0].readOnly) { return };\n      if (document.activeElement !== arguments[0]){\n        arguments[0].focus();\n      }\n      if (arguments[0].value != arguments[1]) {\n        arguments[0].value = arguments[1]\n        arguments[0].dispatchEvent(new InputEvent('input'));\n        arguments[0].dispatchEvent(new Event('change', { bubbles: true }));\n      }\n    JS\n  end\n\n  def set_file(value) # rubocop:disable Naming/AccessorMethodName\n    with_file_detector do\n      path_names = value.to_s.empty? ? [] : value\n      file_names = Array(path_names).map do |pn|\n        Pathname.new(pn).absolute? ? pn : File.expand_path(pn)\n      end.join(\"\\n\")\n      native.send_keys(file_names)\n    end\n  end\n\n  def with_file_detector\n    if driver.options[:browser] == :remote &&\n       bridge.respond_to?(:file_detector) &&\n       bridge.file_detector.nil?\n      begin\n        bridge.file_detector = lambda do |(fn, *)|\n          str = fn.to_s\n          str if File.exist?(str)\n        end\n        yield\n      ensure\n        bridge.file_detector = nil\n      end\n    else\n      yield\n    end\n  end\n\n  def set_content_editable(value) # rubocop:disable Naming/AccessorMethodName\n    # Ensure we are focused on the element\n    click\n\n    editable = driver.execute_script <<-JS, self\n      if (arguments[0].isContentEditable) {\n        var range = document.createRange();\n        var sel = window.getSelection();\n        arguments[0].focus();\n        range.selectNodeContents(arguments[0]);\n        sel.removeAllRanges();\n        sel.addRange(range);\n        return true;\n      }\n      return false;\n    JS\n\n    # The action api has a speed problem but both chrome and firefox 58 raise errors\n    # if we use the faster direct send_keys.  For now just send_keys to the element\n    # we've already focused.\n    # native.send_keys(value.to_s)\n    browser_action.send_keys(value.to_s).perform if editable\n  end\n\n  def action_with_modifiers(click_options)\n    actions = browser_action.tap do |acts|\n      if click_options.coords?\n        if click_options.center_offset?\n          acts.move_to(native, *click_options.coords)\n        else\n          right_by, down_by = *click_options.coords\n          size = native.size\n          left_offset = (size[:width] / 2).to_i\n          top_offset = (size[:height] / 2).to_i\n          left = -left_offset + right_by\n          top = -top_offset + down_by\n          acts.move_to(native, left, top)\n        end\n      else\n        acts.move_to(native)\n      end\n    end\n    modifiers_down(actions, click_options.keys)\n    yield actions\n    modifiers_up(actions, click_options.keys)\n    actions.perform\n  ensure\n    act = browser_action\n    act.release_actions if act.respond_to?(:release_actions)\n  end\n\n  def modifiers_down(actions, keys)\n    each_key(keys) { |key| actions.key_down(key) }\n    actions\n  end\n\n  def modifiers_up(actions, keys)\n    each_key(keys) { |key| actions.key_up(key) }\n    actions\n  end\n\n  def browser\n    driver.browser\n  end\n\n  def bridge\n    browser.send(:bridge)\n  end\n\n  def browser_action\n    browser.action\n  end\n\n  def capabilities\n    browser.capabilities\n  end\n\n  def action_pause(action, duration)\n    action.pause(device: action.pointer_inputs.first, duration: duration)\n  end\n\n  def normalize_keys(keys)\n    keys.map do |key|\n      case key\n      when :ctrl then :control\n      when :command, :cmd then :meta\n      else\n        key\n      end\n    end\n  end\n\n  def each_key(keys, &block)\n    normalize_keys(keys).each(&block)\n  end\n\n  def find_context\n    native\n  end\n\n  def build_node(native_node, initial_cache = {})\n    self.class.new(driver, native_node, initial_cache)\n  end\n\n  def attrs(*attr_names)\n    return attr_names.map { |name| self[name.to_s] } if ENV['CAPYBARA_THOROUGH']\n\n    driver.evaluate_script <<~JS, self, attr_names.map(&:to_s)\n      (function(el, names){\n        return names.map(function(name){\n          return el[name]\n        });\n      })(arguments[0], arguments[1]);\n    JS\n  end\n\n  def native_id\n    # Selenium 3 -> 4 changed the return of ref\n    type_or_id, id = native.ref\n    id || type_or_id\n  end\n\n  def shadow_root?\n    defined?(::Selenium::WebDriver::ShadowRoot) && native.is_a?(::Selenium::WebDriver::ShadowRoot)\n  end\n\n  GET_XPATH_SCRIPT = <<~'JS'\n    (function(el, xml){\n      var xpath = '';\n    \tvar pos, tempitem2;\n\n      if (el.getRootNode && el.getRootNode() instanceof ShadowRoot) {\n        return \"(: Shadow DOM element - no XPath :)\";\n      };\n      while(el !== xml.documentElement) {\n        pos = 0;\n        tempitem2 = el;\n        while(tempitem2) {\n          if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name\n            pos += 1;\n          }\n          tempitem2 = tempitem2.previousSibling;\n        }\n\n        if (el.namespaceURI != xml.documentElement.namespaceURI) {\n          xpath = \"*[local-name()='\"+el.nodeName+\"' and namespace-uri()='\"+(el.namespaceURI===null?'':el.namespaceURI)+\"'][\"+pos+']'+'/'+xpath;\n        } else {\n          xpath = el.nodeName.toUpperCase()+\"[\"+pos+\"]/\"+xpath;\n        }\n\n        el = el.parentNode;\n      }\n      xpath = '/'+xml.documentElement.nodeName.toUpperCase()+'/'+xpath;\n      xpath = xpath.replace(/\\/$/, '');\n      return xpath;\n    })(arguments[0], document)\n  JS\n\n  OBSCURED_OR_OFFSET_SCRIPT = <<~JS\n    (function(el, x, y) {\n      var box = el.getBoundingClientRect();\n      if (x == null) x = box.width/2;\n      if (y == null) y = box.height/2 ;\n\n      var px = box.left + x,\n          py = box.top + y,\n          e = document.elementFromPoint(px, py);\n\n      if (!el.contains(e))\n        return true;\n\n      return { x: px, y: py };\n    })(arguments[0], arguments[1], arguments[2])\n  JS\n\n  RAPID_APPEND_TEXT = <<~JS\n    (function(el, value) {\n      value = el.value + value;\n      if (el.maxLength && el.maxLength != -1){\n        value = value.slice(0, el.maxLength);\n      }\n      el.value = value;\n    })(arguments[0], arguments[1])\n  JS\n\n  # SettableValue encapsulates time/date field formatting\n  class SettableValue\n    attr_reader :value\n\n    def initialize(value)\n      @value = value\n    end\n\n    def to_s\n      value.to_s\n    end\n\n    def dateable?\n      !value.is_a?(String) && value.respond_to?(:to_date)\n    end\n\n    def to_date_str\n      value.to_date.iso8601\n    end\n\n    def timeable?\n      !value.is_a?(String) && value.respond_to?(:to_time)\n    end\n\n    def to_time_str\n      value.to_time.strftime('%H:%M')\n    end\n\n    def to_datetime_str\n      value.to_time.strftime('%Y-%m-%dT%H:%M')\n    end\n  end\n  private_constant :SettableValue\n\n  # ClickOptions encapsulates click option logic\n  class ClickOptions\n    attr_reader :keys, :options\n\n    def initialize(keys, options)\n      @keys = keys\n      @options = options\n    end\n\n    def coords?\n      options[:x] && options[:y]\n    end\n\n    def coords\n      [options[:x], options[:y]]\n    end\n\n    def center_offset?\n      options[:offset] == :center\n    end\n\n    def empty?\n      keys.empty? && !coords? && delay.zero?\n    end\n\n    def delay\n      options[:delay] || 0\n    end\n  end\n  private_constant :ClickOptions\nend\n"
  },
  {
    "path": "lib/capybara/selenium/nodes/chrome_node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/extensions/html5_drag'\nrequire 'capybara/selenium/extensions/file_input_click_emulation'\n\nclass Capybara::Selenium::ChromeNode < Capybara::Selenium::Node\n  include Html5Drag\n  include FileInputClickEmulation\n\n  def set_text(value, clear: nil, **_unused)\n    super.tap do\n      # React doesn't see the chromedriver element clear\n      send_keys(:space, :backspace) if value.to_s.empty? && clear.nil?\n    end\n  end\n\n  def set_file(value) # rubocop:disable Naming/AccessorMethodName\n    # In Chrome 75+ files are appended (due to WebDriver spec - why?) so we have to clear here if its multiple and already set\n    if browser_version >= 75.0\n      driver.execute_script(<<~JS, self)\n        if (arguments[0].multiple && arguments[0].files.length){\n          arguments[0].value = null;\n        }\n      JS\n    end\n    super\n  end\n\n  def drop(*args)\n    html5_drop(*args)\n  end\n\n  def click(*, **)\n    super\n  rescue ::Selenium::WebDriver::Error::ElementClickInterceptedError\n    raise\n  rescue ::Selenium::WebDriver::Error::WebDriverError => e\n    # chromedriver 74 (at least on mac) raises the wrong error for this\n    if e.message.include?('element click intercepted')\n      raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message\n    end\n\n    raise\n  end\n\n  def disabled?\n    driver.evaluate_script(\"arguments[0].matches(':disabled, select:disabled *')\", self)\n  end\n\n  def select_option\n    # To optimize to only one check and then click\n    selected_or_disabled = driver.evaluate_script(<<~JS, self)\n      arguments[0].matches(':disabled, select:disabled *, :checked')\n    JS\n    click unless selected_or_disabled\n  end\n\n  def visible?\n    return super unless native_displayed?\n\n    begin\n      bridge.send(:execute, :is_element_displayed, id: native_id)\n    rescue Selenium::WebDriver::Error::UnknownCommandError\n      # If the is_element_displayed command is unknown, no point in trying again\n      driver.options[:native_displayed] = false\n      super\n    end\n  end\n\n  def send_keys(*args)\n    args.chunk { |inp| inp.is_a?(String) && inp.match?(/\\p{Emoji Presentation}/) }\n        .each do |contains_emoji, inputs|\n      if contains_emoji\n        inputs.join.grapheme_clusters.chunk { |gc| gc.match?(/\\p{Emoji Presentation}/) }\n              .each do |emoji, clusters|\n          if emoji\n            driver.send(:execute_cdp, 'Input.insertText', text: clusters.join)\n          else\n            super(clusters.join)\n          end\n        end\n      else\n        super(*inputs)\n      end\n    end\n  end\n\nprotected\n\n  def catch_error?(error, errors = nil)\n    # Selenium::WebDriver::Error::UnknownError:\n    #    unknown error: unhandled inspector error: {\"code\":-32000,\"message\":\"Node with given id does not belong to the document\"}\n    super ||\n      (error.is_a?(Selenium::WebDriver::Error::UnknownError) &&\n       error.message.include?('Node with given id does not belong to the document'))\n  end\n\nprivate\n\n  def perform_legacy_drag(element, drop_modifiers)\n    return super if chromedriver_fixed_actions_key_state? || element.obscured?\n\n    raise ArgumentError, 'Modifier keys are not supported while dragging in this version of Chrome.' unless drop_modifiers.empty?\n\n    # W3C Chrome/chromedriver < 77 doesn't maintain mouse button state across actions API performs\n    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2981\n    browser_action.release.perform\n    browser_action.click_and_hold(native).move_to(element.native).release.perform\n  end\n\n  def browser_version(to_float: true)\n    caps = capabilities\n    ver = caps[:browser_version] || caps[:version]\n    ver = ver.to_f if to_float\n    ver\n  end\n\n  def chromedriver_fixed_actions_key_state?\n    Gem::Requirement.new('>= 76.0.3809.68').satisfied_by?(chromedriver_version)\n  end\n\n  def chromedriver_supports_displayed_endpoint?\n    Gem::Requirement.new('>= 76.0.3809.25').satisfied_by?(chromedriver_version)\n  end\n\n  def chromedriver_version\n    Gem::Version.new(capabilities['chrome']['chromedriverVersion'].split(' ')[0]) # rubocop:disable Style/RedundantArgument\n  end\n\n  def native_displayed?\n    (driver.options[:native_displayed] != false) &&\n      chromedriver_supports_displayed_endpoint? &&\n      !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/nodes/edge_node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/extensions/html5_drag'\n\nclass Capybara::Selenium::EdgeNode < Capybara::Selenium::Node\n  include Html5Drag\n\n  def set_text(value, clear: nil, **_unused)\n    return super unless chrome_edge?\n\n    super.tap do\n      # React doesn't see the chromedriver element clear\n      send_keys(:space, :backspace) if value.to_s.empty? && clear.nil?\n    end\n  end\n\n  def set_file(value) # rubocop:disable Naming/AccessorMethodName\n    # In Chrome 75+ files are appended (due to WebDriver spec - why?) so we have to clear here if its multiple and already set\n    if chrome_edge?\n      driver.execute_script(<<~JS, self)\n        if (arguments[0].multiple && arguments[0].files.length){\n          arguments[0].value = null;\n        }\n      JS\n    end\n    super\n  end\n\n  def drop(*args)\n    return super unless chrome_edge?\n\n    html5_drop(*args)\n  end\n\n  def click(*, **)\n    super\n  rescue Selenium::WebDriver::Error::InvalidArgumentError => e\n    tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase }\n    if tag_name == 'input' && type == 'file'\n      raise Selenium::WebDriver::Error::InvalidArgumentError, \"EdgeChrome can't click on file inputs.\\n#{e.message}\"\n    end\n\n    raise\n  end\n\n  def disabled?\n    return super unless chrome_edge?\n\n    driver.evaluate_script(\"arguments[0].matches(':disabled, select:disabled *')\", self)\n  end\n\n  def select_option\n    return super unless chrome_edge?\n\n    # To optimize to only one check and then click\n    selected_or_disabled = driver.evaluate_script(<<~JS, self)\n      arguments[0].matches(':disabled, select:disabled *, :checked')\n    JS\n    click unless selected_or_disabled\n  end\n\n  def visible?\n    return super unless chrome_edge? && native_displayed?\n\n    begin\n      bridge.send(:execute, :is_element_displayed, id: native_id)\n    rescue Selenium::WebDriver::Error::UnknownCommandError\n      # If the is_element_displayed command is unknown, no point in trying again\n      driver.options[:native_displayed] = false\n      super\n    end\n  end\n\n  def send_keys(*args)\n    args.chunk { |inp| inp.is_a?(String) && inp.match?(/\\p{Emoji Presentation}/) }\n        .each do |contains_emoji, inputs|\n      if contains_emoji\n        inputs.join.grapheme_clusters.chunk { |gc| gc.match?(/\\p{Emoji Presentation}/) }\n              .each do |emoji, clusters|\n          if emoji\n            driver.send(:execute_cdp, 'Input.insertText', text: clusters.join)\n          else\n            super(clusters.join)\n          end\n        end\n      else\n        super(*inputs)\n      end\n    end\n  end\n\nprivate\n\n  def browser_version\n    @browser_version ||= begin\n      caps = driver.browser.capabilities\n      (caps[:browser_version] || caps[:version]).to_f\n    end\n  end\n\n  def chrome_edge?\n    browser_version >= 75\n  end\n\n  def native_displayed?\n    (driver.options[:native_displayed] != false) &&\n      # chromedriver_supports_displayed_endpoint? &&\n      !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/nodes/firefox_node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/extensions/html5_drag'\nrequire 'capybara/selenium/extensions/file_input_click_emulation'\n\nclass Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node\n  include Html5Drag\n  include FileInputClickEmulation\n\n  def click(keys = [], **options)\n    super\n  rescue ::Selenium::WebDriver::Error::ElementNotInteractableError\n    if tag_name == 'tr'\n      warn 'You are attempting to click a table row which has issues in geckodriver/marionette - ' \\\n           'see https://github.com/mozilla/geckodriver/issues/1228 - Your test should probably be ' \\\n           'clicking on a table cell like a user would. Clicking the first cell in the row instead.'\n      return find_css('th:first-child,td:first-child')[0].click(keys, **options)\n    end\n    raise\n  end\n\n  def disabled?\n    driver.evaluate_script(\"arguments[0].matches(':disabled, select:disabled *')\", self)\n  end\n\n  def set_file(value) # rubocop:disable Naming/AccessorMethodName\n    # By default files are appended so we have to clear here if its multiple and already set\n    driver.execute_script(<<~JS, self)\n      if (arguments[0].multiple && arguments[0].files.length){\n        arguments[0].value = null;\n      }\n    JS\n    return super if browser_version >= 62.0\n\n    # Workaround lack of support for multiple upload by uploading one at a time\n    path_names = value.to_s.empty? ? [] : Array(value)\n    if (fd = bridge.file_detector) && !driver.browser.respond_to?(:upload)\n      path_names.map! { |path| upload(fd.call([path])) || path }\n    end\n    path_names.each { |path| native.send_keys(path) }\n  end\n\n  def focused?\n    driver.evaluate_script('arguments[0] == document.activeElement', self)\n  end\n\n  def send_keys(*args)\n    # https://github.com/mozilla/geckodriver/issues/846\n    return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)\n\n    native.click unless focused?\n\n    _send_keys(args).perform\n  end\n\n  def drop(*args)\n    html5_drop(*args)\n  end\n\n  def hover\n    return super unless browser_version >= 65.0\n\n    # work around issue 2156 - https://github.com/teamcapybara/capybara/issues/2156\n    scroll_if_needed { browser_action.move_to(native, 0, 0).move_to(native).perform }\n  end\n\n  def select_option\n    # To optimize to only one check and then click\n    selected_or_disabled = driver.evaluate_script(<<~JS, self)\n      arguments[0].matches(':disabled, select:disabled *, :checked')\n    JS\n    click unless selected_or_disabled\n  end\n\n  def visible?\n    return super unless native_displayed?\n\n    begin\n      bridge.send(:execute, :is_element_displayed, id: native_id)\n    rescue Selenium::WebDriver::Error::UnknownCommandError\n      # If the is_element_displayed command is unknown, no point in trying again\n      driver.options[:native_displayed] = false\n      super\n    end\n  end\n\nprivate\n\n  def native_displayed?\n    (driver.options[:native_displayed] != false) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']\n  end\n\n  def perform_with_options(click_options)\n    # Firefox/marionette has an issue clicking with offset near viewport edge\n    # scroll element to middle just in case\n    scroll_to_center if click_options.coords?\n    super\n  end\n\n  def _send_keys(keys, actions = browser_action, down_keys = ModifierKeysStack.new)\n    case keys\n    when :control, :left_control, :right_control,\n         :alt, :left_alt, :right_alt,\n         :shift, :left_shift, :right_shift,\n         :meta, :left_meta, :right_meta,\n         :command\n      down_keys.press(keys)\n      actions.key_down(keys)\n    when String\n      # https://bugzilla.mozilla.org/show_bug.cgi?id=1405370\n      keys = keys.upcase if (browser_version < 64.0) && down_keys&.include?(:shift)\n      actions.send_keys(keys)\n    when Symbol\n      actions.send_keys(keys)\n    when Array\n      down_keys.push\n      keys.each { |sub_keys| _send_keys(sub_keys, actions, down_keys) }\n      down_keys.pop.reverse_each { |key| actions.key_up(key) }\n    else\n      raise ArgumentError, 'Unknown keys type'\n    end\n    actions\n  end\n\n  def upload(local_file)\n    return nil unless local_file\n    raise ArgumentError, \"You may only upload files: #{local_file.inspect}\" unless File.file?(local_file)\n\n    file = ::Selenium::WebDriver::Zipper.zip_file(local_file)\n    bridge.http.call(:post, \"session/#{bridge.session_id}/file\", file: file)['value']\n  end\n\n  def browser_version\n    driver.browser.capabilities[:browser_version].to_f\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/nodes/ie_node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/selenium/extensions/html5_drag'\n\nclass Capybara::Selenium::IENode < Capybara::Selenium::Node\n  def disabled?\n    # super\n    # optimize to one script call\n    driver.evaluate_script <<~JS.delete(\"\\n\"), self\n      arguments[0].msMatchesSelector('\n        :disabled,\n        select:disabled *,\n        optgroup:disabled *,\n        fieldset[disabled],\n        fieldset[disabled] > *:not(legend),\n        fieldset[disabled] > *:not(legend) *,\n        fieldset[disabled] > legend:nth-of-type(n+2),\n        fieldset[disabled] > legend:nth-of-type(n+2) *\n      ')\n    JS\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/nodes/safari_node.rb",
    "content": "# frozen_string_literal: true\n\n# require 'capybara/selenium/extensions/html5_drag'\nrequire 'capybara/selenium/extensions/modifier_keys_stack'\n\nclass Capybara::Selenium::SafariNode < Capybara::Selenium::Node\n  # include Html5Drag\n\n  def click(keys = [], **options)\n    # driver.execute_script('arguments[0].scrollIntoViewIfNeeded({block: \"center\"})', self)\n    super\n  rescue ::Selenium::WebDriver::Error::ElementNotInteractableError\n    if tag_name == 'tr'\n      warn 'You are attempting to click a table row which has issues in safaridriver - ' \\\n           'Your test should probably be clicking on a table cell like a user would. ' \\\n           'Clicking the first cell in the row instead.'\n      return find_css('th:first-child,td:first-child')[0].click(keys, **options)\n    end\n    raise\n  rescue ::Selenium::WebDriver::Error::WebDriverError => e\n    raise unless e.instance_of? ::Selenium::WebDriver::Error::WebDriverError\n\n    # Safari doesn't return a specific error here - assume it's an ElementNotInteractableError\n    raise ::Selenium::WebDriver::Error::ElementNotInteractableError,\n          'Non distinct error raised in #click, translated to ElementNotInteractableError for retry'\n  end\n\n  def select_option\n    # To optimize to only one check and then click\n    selected_or_disabled = driver.execute_script(<<~JS, self)\n      arguments[0].closest('select').scrollIntoView();\n      return arguments[0].matches(':disabled, select:disabled *, :checked');\n    JS\n    click unless selected_or_disabled\n  end\n\n  def unselect_option\n    driver.execute_script(\"arguments[0].closest('select').scrollIntoView()\", self)\n    super\n  end\n\n  def visible_text\n    return '' unless visible?\n\n    vis_text = driver.execute_script('return arguments[0].innerText', self)\n    vis_text.squeeze(' ')\n            .gsub(/[\\ \\n]*\\n[\\ \\n]*/, \"\\n\")\n            .gsub(/\\A[[:space:]&&[^\\u00a0]]+/, '')\n            .gsub(/[[:space:]&&[^\\u00a0]]+\\z/, '')\n            .tr(\"\\u00a0\", ' ')\n  end\n\n  def disabled?\n    driver.evaluate_script(\"arguments[0].matches(':disabled, select:disabled *')\", self)\n  end\n\n  def set_file(value) # rubocop:disable Naming/AccessorMethodName\n    # By default files are appended so we have to clear here if its multiple and already set\n    native.clear if multiple? && driver.evaluate_script('arguments[0].files', self).any?\n    super\n  end\n\n  def send_keys(*args)\n    if args.none? { |arg| arg.is_a?(Array) || (arg.is_a?(Symbol) && MODIFIER_KEYS.include?(arg)) }\n      return super(*args.map { |arg| arg == :space ? ' ' : arg })\n    end\n\n    native.click\n    _send_keys(args).perform\n  end\n\n  def set_text(value, clear: nil, **_unused)\n    value = value.to_s\n    if clear == :backspace\n      # Clear field by sending the correct number of backspace keys.\n      backspaces = [:backspace] * self.value.to_s.length\n      send_keys([:control, 'e'], *backspaces, value)\n    else\n      super.tap do\n        # React doesn't see the safaridriver element clear\n        send_keys(:space, :backspace) if value.to_s.empty? && clear.nil?\n      end\n    end\n  end\n\n  def hover\n    # Workaround issue where hover would sometimes fail - possibly due to mouse not having moved\n    scroll_if_needed { browser_action.move_to(native, 0, 0).move_to(native).perform }\n  end\n\nprivate\n\n  def _send_keys(keys, actions = browser_action, down_keys = ModifierKeysStack.new)\n    case keys\n    when *MODIFIER_KEYS\n      down_keys.press(keys)\n      actions.key_down(keys)\n    when String\n      keys = keys.upcase if down_keys&.include?(:shift)\n      actions.send_keys(keys)\n    when Symbol\n      actions.send_keys(keys)\n    when Array\n      down_keys.push\n      keys.each { |sub_keys| _send_keys(sub_keys, actions, down_keys) }\n      down_keys.pop.reverse_each { |key| actions.key_up(key) }\n    else\n      raise ArgumentError, 'Unknown keys type'\n    end\n    actions\n  end\n\n  MODIFIER_KEYS = %i[control left_control right_control\n                     alt left_alt right_alt\n                     shift left_shift right_shift\n                     meta left_meta right_meta\n                     command].freeze\nend\n"
  },
  {
    "path": "lib/capybara/selenium/patches/atoms.rb",
    "content": "# frozen_string_literal: true\n\nmodule CapybaraAtoms\nprivate\n\n  def read_atom(function)\n    @atoms ||= Hash.new do |hash, key|\n      hash[key] = begin\n        File.read(File.expand_path(\"../../atoms/#{key}.min.js\", __FILE__))\n      rescue Errno::ENOENT\n        super\n      end\n    end\n    @atoms[function]\n  end\nend\n\nSelenium::WebDriver::Remote::Bridge.prepend CapybaraAtoms unless ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']\n"
  },
  {
    "path": "lib/capybara/selenium/patches/is_displayed.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Selenium\n    module IsDisplayed\n      def commands(command)\n        case command\n        when :is_element_displayed\n          [:get, 'session/:session_id/element/:id/displayed']\n        else\n          super\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/patches/logs.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Selenium\n    module ChromeLogs\n      LOG_MSG = <<~MSG\n        Chromedriver 75+ defaults to W3C mode. Please upgrade to chromedriver >= \\\n        75.0.3770.90 if you need to access logs while in W3C compliant mode.\n      MSG\n\n      COMMANDS = {\n        get_available_log_types: [:get, 'session/:session_id/se/log/types'],\n        get_log: [:post, 'session/:session_id/se/log'],\n        get_log_legacy: [:post, 'session/:session_id/log']\n      }.freeze\n\n      def commands(command)\n        COMMANDS[command] || super\n      end\n\n      def available_log_types\n        types = execute :get_available_log_types\n        Array(types).map(&:to_sym)\n      rescue ::Selenium::WebDriver::Error::UnknownCommandError\n        raise NotImplementedError, LOG_MSG\n      end\n\n      def log(type)\n        data = begin\n          execute :get_log, {}, type: type.to_s\n        rescue ::Selenium::WebDriver::Error::UnknownCommandError\n          execute :get_log_legacy, {}, type: type.to_s\n        end\n\n        Array(data).map do |l|\n          ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')\n        rescue KeyError\n          next\n        end\n      rescue ::Selenium::WebDriver::Error::UnknownCommandError\n        raise NotImplementedError, LOG_MSG\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/selenium/patches/pause_duration_fix.rb",
    "content": "# frozen_string_literal: true\n\nmodule PauseDurationFix\n  def encode\n    super.tap { |output| output[:duration] ||= 0 }\n  end\nend\n\nSelenium::WebDriver::Interactions::Pause.prepend PauseDurationFix\n"
  },
  {
    "path": "lib/capybara/selenium/patches/persistent_client.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module Selenium\n    class PersistentClient < ::Selenium::WebDriver::Remote::Http::Default\n      def close\n        super\n        @http.finish if @http&.started?\n      end\n\n    private\n\n      def http\n        super.tap do |http|\n          http.start unless http.started?\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/server/animation_disabler.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  class Server\n    class AnimationDisabler\n      def self.selector_for(css_or_bool)\n        case css_or_bool\n        when String\n          css_or_bool\n        when true\n          '*'\n        else\n          raise CapybaraError, 'Capybara.disable_animation supports either a String (the css selector to disable) or a boolean'\n        end\n      end\n\n      def initialize(app)\n        @app = app\n        @disable_css_markup = format(DISABLE_CSS_MARKUP_TEMPLATE,\n                                     selector: self.class.selector_for(Capybara.disable_animation))\n        @disable_js_markup = +DISABLE_JS_MARKUP_TEMPLATE\n      end\n\n      def call(env)\n        status, headers, body = @app.call(env)\n        return [status, headers, body] unless html_content?(headers)\n\n        nonces = directive_nonces(headers).transform_values { |nonce| \"nonce=\\\"#{nonce}\\\"\" if nonce && !nonce.empty? }\n        response = Rack::Response.new([], status, headers)\n\n        body.each { |html| response.write insert_disable(html, nonces) }\n        body.close if body.respond_to?(:close)\n\n        response.finish\n      end\n\n    private\n\n      attr_reader :disable_css_markup, :disable_js_markup\n\n      def html_content?(headers)\n        /html/.match?(headers['Content-Type']) # rubocop:todo Performance/StringInclude\n      end\n\n      def insert_disable(html, nonces)\n        html.sub(%r{(</head>)}, \"<style #{nonces['style-src']}>#{disable_css_markup}</style>\\\\1\")\n            .sub(%r{(</body>)}, \"<script #{nonces['script-src']}>#{disable_js_markup}</script>\\\\1\")\n      end\n\n      def directive_nonces(headers)\n        headers.fetch('Content-Security-Policy', '')\n               .split(';')\n               .map(&:split)\n               .to_h do |s|\n                 [\n                   s[0], s[1..].filter_map do |value|\n                     /^'nonce-(?<nonce>.+)'/ =~ value\n                     nonce\n                   end[0]\n                 ]\n               end\n      end\n\n      DISABLE_CSS_MARKUP_TEMPLATE = <<~CSS\n        %<selector>s, %<selector>s::before, %<selector>s::after {\n           transition: none !important;\n           animation-duration: 0s !important;\n           animation-delay: 0s !important;\n           scroll-behavior: auto !important;\n        }\n      CSS\n\n      DISABLE_JS_MARKUP_TEMPLATE = <<~SCRIPT\n        //<![CDATA[\n          (typeof jQuery !== 'undefined') && (jQuery.fx.off = true);\n        //]]>\n      SCRIPT\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/server/checker.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  class Server\n    class Checker\n      TRY_HTTPS_ERRORS = [EOFError, Net::ReadTimeout, Errno::ECONNRESET].freeze\n\n      def initialize(host, port)\n        @host, @port = host, port\n        @ssl = false\n      end\n\n      def request(&block)\n        ssl? ? https_request(&block) : http_request(&block)\n      rescue *TRY_HTTPS_ERRORS\n        res = https_request(&block)\n        @ssl = true\n        res\n      end\n\n      def ssl?\n        @ssl\n      end\n\n    private\n\n      def http_request(&block)\n        make_request(read_timeout: 2, &block)\n      end\n\n      def https_request(&block)\n        make_request(**ssl_options, &block)\n      end\n\n      def make_request(**options, &block)\n        Net::HTTP.start(@host, @port, options.merge(max_retries: 0), &block)\n      end\n\n      def ssl_options\n        { use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE }\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/server/middleware.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  class Server\n    class Middleware\n      class Counter\n        def initialize\n          @value = []\n          @mutex = Mutex.new\n        end\n\n        def increment(uri)\n          @mutex.synchronize { @value.push(uri) }\n        end\n\n        def decrement(uri)\n          @mutex.synchronize { @value.delete_at(@value.index(uri) || - 1) }\n        end\n\n        def positive?\n          @mutex.synchronize { @value.length.positive? }\n        end\n\n        def value\n          @mutex.synchronize { @value.dup }\n        end\n      end\n\n      attr_reader :error\n\n      def initialize(app, server_errors, extra_middleware = [])\n        @app = app\n        @extended_app = extra_middleware.inject(@app) do |ex_app, klass|\n          klass.new(ex_app)\n        end\n        @counter = Counter.new\n        @server_errors = server_errors\n      end\n\n      def pending_requests\n        @counter.value\n      end\n\n      def pending_requests?\n        @counter.positive?\n      end\n\n      def clear_error\n        @error = nil\n      end\n\n      def call(env)\n        if env['PATH_INFO'] == '/__identify__'\n          [200, {}, [@app.object_id.to_s]]\n        else\n          request_uri = env['REQUEST_URI']\n          @counter.increment(request_uri)\n\n          begin\n            @extended_app.call(env)\n          rescue *@server_errors => e\n            @error ||= e\n            raise e\n          ensure\n            @counter.decrement(request_uri)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/server.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'uri'\nrequire 'net/http'\nrequire 'rack'\nrequire 'capybara/server/middleware'\nrequire 'capybara/server/animation_disabler'\nrequire 'capybara/server/checker'\n\nmodule Capybara\n  # @api private\n  class Server\n    class << self\n      def ports\n        @ports ||= {}\n      end\n    end\n\n    attr_reader :app, :port, :host\n\n    def initialize(app,\n                   *deprecated_options,\n                   port: Capybara.server_port,\n                   host: Capybara.server_host,\n                   reportable_errors: Capybara.server_errors,\n                   extra_middleware: [])\n      unless deprecated_options.empty?\n        warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments'\n      end\n      @app = app\n      @extra_middleware = extra_middleware\n      @server_thread = nil # suppress warnings\n      @host = deprecated_options[1] || host\n      @reportable_errors = deprecated_options[2] || reportable_errors\n      @port = deprecated_options[0] || port\n      @port ||= Capybara::Server.ports[port_key]\n      @port ||= find_available_port(host)\n      @checker = Checker.new(@host, @port)\n    end\n\n    def reset_error!\n      middleware.clear_error\n    end\n\n    def error\n      middleware.error\n    end\n\n    def using_ssl?\n      @checker.ssl?\n    end\n\n    def responsive?\n      return false if @server_thread&.join(0)\n\n      res = @checker.request { |http| http.get('/__identify__') }\n\n      res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)\n    rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError\n      false\n    end\n\n    def wait_for_pending_requests\n      timer = Capybara::Helpers.timer(expire_in: 60)\n      while pending_requests?\n        raise \"Requests did not finish in 60 seconds: #{middleware.pending_requests}\" if timer.expired?\n\n        sleep 0.01\n      end\n    end\n\n    def boot\n      unless responsive?\n        Capybara::Server.ports[port_key] = port\n\n        @server_thread = Thread.new do\n          Capybara.server.call(middleware, port, host)\n        end\n\n        timer = Capybara::Helpers.timer(expire_in: 60)\n        until responsive?\n          raise 'Rack application timed out during boot' if timer.expired?\n\n          @server_thread.join(0.1)\n        end\n      end\n\n      self\n    end\n\n    def base_url\n      \"http#{'s' if using_ssl?}://#{host}:#{port}\"\n    end\n\n  private\n\n    def middleware\n      @middleware ||= Middleware.new(app, @reportable_errors, @extra_middleware)\n    end\n\n    def port_key\n      Capybara.reuse_server ? app.object_id : middleware.object_id\n    end\n\n    def pending_requests?\n      middleware.pending_requests?\n    end\n\n    def find_available_port(host)\n      server = TCPServer.new(host, 0)\n      port = server.addr[1]\n      server.close\n\n      # Workaround issue where some platforms (mac, ???) when passed a host\n      # of '0.0.0.0' will return a port that is only available on one of the\n      # ip addresses that resolves to, but the next binding to that port requires\n      # that port to be available on all ips\n      server = TCPServer.new(host, port)\n      port\n    rescue Errno::EADDRINUSE\n      retry\n    ensure\n      server&.close\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/session/config.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'delegate'\n\nmodule Capybara\n  class SessionConfig\n    OPTIONS = %i[always_include_port run_server default_selector default_max_wait_time ignore_hidden_elements\n                 automatic_reload match exact exact_text raise_server_errors visible_text_only\n                 automatic_label_click enable_aria_label save_path asset_host default_host app_host\n                 server_host server_port server_errors default_set_options disable_animation test_id\n                 predicates_wait default_normalize_ws w3c_click_offset enable_aria_role default_retry_interval].freeze\n\n    attr_accessor(*OPTIONS)\n\n    ##\n    # @!method always_include_port\n    #   See {Capybara.configure}\n    # @!method run_server\n    #   See {Capybara.configure}\n    # @!method default_selector\n    #   See {Capybara.configure}\n    # @!method default_max_wait_time\n    #   See {Capybara.configure}\n    # @!method default_retry_interval\n    #   See {Capybara.configure}\n    # @!method ignore_hidden_elements\n    #   See {Capybara.configure}\n    # @!method automatic_reload\n    #   See {Capybara.configure}\n    # @!method match\n    #   See {Capybara.configure}\n    # @!method exact\n    #   See {Capybara.configure}\n    # @!method raise_server_errors\n    #   See {Capybara.configure}\n    # @!method visible_text_only\n    #   See {Capybara.configure}\n    # @!method automatic_label_click\n    #   See {Capybara.configure}\n    # @!method enable_aria_label\n    #   See {Capybara.configure}\n    # @!method enable_aria_role\n    #   See {Capybara.configure}\n    # @!method save_path\n    #   See {Capybara.configure}\n    # @!method asset_host\n    #   See {Capybara.configure}\n    # @!method default_host\n    #   See {Capybara.configure}\n    # @!method app_host\n    #   See {Capybara.configure}\n    # @!method server_host\n    #   See {Capybara.configure}\n    # @!method server_port\n    #   See {Capybara.configure}\n    # @!method server_errors\n    #   See {Capybara.configure}\n    # @!method default_set_options\n    #   See {Capybara.configure}\n    # @!method disable_animation\n    #   See {Capybara.configure}\n    # @!method test_id\n    #   See {Capybara.configure}\n    # @!method default_normalize_ws\n    #   See {Capybara.configure}\n    # @!method w3c_click_offset\n    #   See {Capybara.configure}\n\n    remove_method :server_host\n\n    ##\n    #\n    # @return [String]    The IP address bound by default server\n    #\n    def server_host\n      @server_host || '127.0.0.1'\n    end\n\n    remove_method :server_errors=\n    def server_errors=(errors)\n      (@server_errors ||= []).replace(errors.dup)\n    end\n\n    remove_method :app_host=\n    def app_host=(url)\n      unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)\n        raise ArgumentError, \"Capybara.app_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}.\"\n      end\n\n      @app_host = url\n    end\n\n    remove_method :default_host=\n    def default_host=(url)\n      unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)\n        raise ArgumentError, \"Capybara.default_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}.\"\n      end\n\n      @default_host = url\n    end\n\n    remove_method :test_id=\n    ##\n    #\n    # Set an attribute to be optionally matched against the locator for builtin selector types.\n    # This attribute will be checked by builtin selector types whenever id would normally be checked.\n    # If `nil` then it will be ignored.\n    #\n    # @param [String, Symbol, nil] id Name of the attribute to use as the test id\n    #\n    def test_id=(id)\n      @test_id = id&.to_sym\n    end\n\n    def initialize_copy(other)\n      super\n      @server_errors = @server_errors.dup\n    end\n  end\n\n  class ReadOnlySessionConfig < SimpleDelegator\n    SessionConfig::OPTIONS.each do |option|\n      define_method \"#{option}=\" do |_|\n        raise 'Per session settings are only supported when Capybara.threadsafe == true'\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/session/matchers.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  module SessionMatchers\n    ##\n    # Asserts that the page has the given path.\n    # By default, if passed a full url this will compare against the full url,\n    # if passed a path only the path+query portion will be compared, if passed a regexp\n    # the comparison will depend on the :url option (path+query by default)\n    #\n    # @!macro current_path_query_params\n    #   @overload $0(string, **options)\n    #     @param string [String]           The string that the current 'path' should equal\n    #   @overload $0(regexp, **options)\n    #     @param regexp [Regexp]           The regexp that the current 'path' should match to\n    #   @option options [Boolean] :url (true if `string` is a full url, otherwise false) Whether the comparison should be done against the full current url or just the path\n    #   @option options [Boolean] :ignore_query (false)  Whether the query portion of the current url/path should be ignored\n    #   @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for the current url/path to eq/match given string/regexp argument\n    # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n    # @return [true]\n    #\n    def assert_current_path(path, **options, &optional_filter_block)\n      _verify_current_path(path, optional_filter_block, **options) do |query|\n        raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)\n      end\n    end\n\n    ##\n    # Asserts that the page doesn't have the given path.\n    # By default, if passed a full url this will compare against the full url,\n    # if passed a path only the path+query portion will be compared, if passed a regexp\n    # the comparison will depend on the :url option\n    #\n    # @macro current_path_query_params\n    # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time\n    # @return [true]\n    #\n    def assert_no_current_path(path, **options, &optional_filter_block)\n      _verify_current_path(path, optional_filter_block, **options) do |query|\n        raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)\n      end\n    end\n\n    ##\n    # Checks if the page has the given path.\n    # By default, if passed a full url this will compare against the full url,\n    # if passed a path only the path+query portion will be compared, if passed a regexp\n    # the comparison will depend on the :url option\n    #\n    # @macro current_path_query_params\n    # @return [Boolean]\n    #\n    def has_current_path?(path, **options, &optional_filter_block)\n      make_predicate(options) { assert_current_path(path, **options, &optional_filter_block) }\n    end\n\n    ##\n    # Checks if the page doesn't have the given path.\n    # By default, if passed a full url this will compare against the full url,\n    # if passed a path only the path+query portion will be compared, if passed a regexp\n    # the comparison will depend on the :url option\n    #\n    # @macro current_path_query_params\n    # @return [Boolean]\n    #\n    def has_no_current_path?(path, **options, &optional_filter_block)\n      make_predicate(options) { assert_no_current_path(path, **options, &optional_filter_block) }\n    end\n\n  private\n\n    def _verify_current_path(path, filter_block, **options)\n      query = Capybara::Queries::CurrentPathQuery.new(path, **options, &filter_block)\n      document.synchronize(query.wait) do\n        yield(query)\n      end\n      true\n    end\n\n    def make_predicate(options)\n      options[:wait] = 0 unless options.key?(:wait) || config.predicates_wait\n      yield\n    rescue Capybara::ExpectationNotMet\n      false\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/session.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/session/matchers'\nrequire 'addressable/uri'\n\nmodule Capybara\n  ##\n  #\n  # The {Session} class represents a single user's interaction with the system. The {Session} can use\n  # any of the underlying drivers. A session can be initialized manually like this:\n  #\n  #     session = Capybara::Session.new(:culerity, MyRackApp)\n  #\n  # The application given as the second argument is optional. When running Capybara against an external\n  # page, you might want to leave it out:\n  #\n  #     session = Capybara::Session.new(:culerity)\n  #     session.visit('http://www.google.com')\n  #\n  # When {Capybara.configure threadsafe} is `true` the sessions options will be initially set to the\n  # current values of the global options and a configuration block can be passed to the session initializer.\n  # For available options see {Capybara::SessionConfig::OPTIONS}:\n  #\n  #     session = Capybara::Session.new(:driver, MyRackApp) do |config|\n  #       config.app_host = \"http://my_host.dev\"\n  #     end\n  #\n  # The {Session} provides a number of methods for controlling the navigation of the page, such as {#visit},\n  # {#current_path}, and so on. It also delegates a number of methods to a {Capybara::Document}, representing\n  # the current HTML document. This allows interaction:\n  #\n  #     session.fill_in('q', with: 'Capybara')\n  #     session.click_button('Search')\n  #     expect(session).to have_content('Capybara')\n  #\n  # When using `capybara/dsl`, the {Session} is initialized automatically for you.\n  #\n  class Session\n    include Capybara::SessionMatchers\n\n    NODE_METHODS = %i[\n      all first attach_file text check choose scroll_to scroll_by\n      click double_click right_click\n      click_link_or_button click_button click_link\n      fill_in find find_all find_button find_by_id find_field find_link\n      has_content? has_text? has_css? has_no_content? has_no_text?\n      has_no_css? has_no_xpath? has_xpath? select uncheck\n      has_element? has_no_element?\n      has_link? has_no_link? has_button? has_no_button? has_field?\n      has_no_field? has_checked_field? has_unchecked_field?\n      has_no_table? has_table? unselect has_select? has_no_select?\n      has_selector? has_no_selector? click_on has_no_checked_field?\n      has_no_unchecked_field? query assert_selector assert_no_selector\n      assert_all_of_selectors assert_none_of_selectors assert_any_of_selectors\n      refute_selector assert_text assert_no_text\n    ].freeze\n    # @api private\n    DOCUMENT_METHODS = %i[\n      title assert_title assert_no_title has_title? has_no_title?\n    ].freeze\n    SESSION_METHODS = %i[\n      body html source current_url current_host current_path\n      execute_script evaluate_script evaluate_async_script visit refresh go_back go_forward send_keys\n      within within_element within_fieldset within_table within_frame switch_to_frame\n      current_window windows open_new_window switch_to_window within_window window_opened_by\n      save_page save_and_open_page save_screenshot\n      save_and_open_screenshot reset_session! response_headers\n      status_code current_scope\n      assert_current_path assert_no_current_path has_current_path? has_no_current_path?\n    ].freeze + DOCUMENT_METHODS\n    MODAL_METHODS = %i[\n      accept_alert accept_confirm dismiss_confirm accept_prompt dismiss_prompt\n    ].freeze\n    DSL_METHODS = NODE_METHODS + SESSION_METHODS + MODAL_METHODS\n\n    attr_reader :mode, :app, :server\n    attr_accessor :synchronized\n\n    def initialize(mode, app = nil)\n      if app && !app.respond_to?(:call)\n        raise TypeError, 'The second parameter to Session::new should be a rack app if passed.'\n      end\n\n      @@instance_created = true # rubocop:disable Style/ClassVars\n      @mode = mode\n      @app = app\n      if block_given?\n        raise 'A configuration block is only accepted when Capybara.threadsafe == true' unless Capybara.threadsafe\n\n        yield config\n      end\n      @server = if config.run_server && @app && driver.needs_server?\n        server_options = { port: config.server_port, host: config.server_host, reportable_errors: config.server_errors }\n        server_options[:extra_middleware] = [Capybara::Server::AnimationDisabler] if config.disable_animation\n        Capybara::Server.new(@app, **server_options).boot\n      end\n      @touched = false\n    end\n\n    def driver\n      @driver ||= begin\n        unless Capybara.drivers[mode]\n          other_drivers = Capybara.drivers.names.map(&:inspect)\n          raise Capybara::DriverNotFoundError, \"no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}\"\n        end\n        driver = Capybara.drivers[mode].call(app)\n        driver.session = self if driver.respond_to?(:session=)\n        driver\n      end\n    end\n\n    ##\n    #\n    # Reset the session (i.e. remove cookies and navigate to blank page).\n    #\n    # This method does not:\n    #\n    # * accept modal dialogs if they are present (Selenium driver now does, others may not)\n    # * clear browser cache/HTML 5 local storage/IndexedDB/Web SQL database/etc.\n    # * modify state of the driver/underlying browser in any other way\n    #\n    # as doing so will result in performance downsides and it's not needed to do everything from the list above for most apps.\n    #\n    # If you want to do anything from the list above on a general basis you can:\n    #\n    # * write RSpec/Cucumber/etc. after hook\n    # * monkeypatch this method\n    # * use Ruby's `prepend` method\n    #\n    def reset!\n      if @touched\n        driver.reset!\n        @touched = false\n        switch_to_frame(:top) rescue nil # rubocop:disable Style/RescueModifier\n        @scopes = [nil]\n      end\n      @server&.wait_for_pending_requests\n      raise_server_error!\n    end\n    alias_method :cleanup!, :reset!\n    alias_method :reset_session!, :reset!\n\n    ##\n    #\n    # Disconnect from the current driver. A new driver will be instantiated on the next interaction.\n    #\n    def quit\n      @driver.quit if @driver.respond_to? :quit\n      @document = @driver = nil\n      @touched = false\n      @server&.reset_error!\n    end\n\n    ##\n    #\n    # Raise errors encountered in the server.\n    #\n    def raise_server_error!\n      return unless @server&.error\n\n      # Force an explanation for the error being raised as the exception cause\n      begin\n        if config.raise_server_errors\n          raise CapybaraError, 'Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true'\n        end\n      rescue CapybaraError => capy_error # rubocop:disable Naming/RescuedExceptionsVariableName\n        raise @server.error, cause: capy_error\n      ensure\n        @server.reset_error!\n      end\n    end\n\n    ##\n    #\n    # Returns a hash of response headers. Not supported by all drivers (e.g. Selenium).\n    #\n    # @return [Hash<String, String>] A hash of response headers.\n    #\n    def response_headers\n      driver.response_headers\n    end\n\n    ##\n    #\n    # Returns the current HTTP status code as an integer. Not supported by all drivers (e.g. Selenium).\n    #\n    # @return [Integer] Current HTTP status code\n    #\n    def status_code\n      driver.status_code\n    end\n\n    ##\n    #\n    # @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).\n    #\n    def html\n      driver.html || ''\n    end\n    alias_method :body, :html\n    alias_method :source, :html\n\n    ##\n    #\n    # @return [String] Path of the current page, without any domain information\n    #\n    def current_path\n      # Addressable parsing is more lenient than URI\n      uri = ::Addressable::URI.parse(current_url)\n\n      # Addressable doesn't support opaque URIs - we want nil here\n      return nil if uri&.scheme == 'about'\n\n      path = uri&.path\n      path unless path&.empty?\n    end\n\n    ##\n    #\n    # @return [String] Host of the current page\n    #\n    def current_host\n      uri = URI.parse(current_url)\n      \"#{uri.scheme}://#{uri.host}\" if uri.host\n    end\n\n    ##\n    #\n    # @return [String] Fully qualified URL of the current page\n    #\n    def current_url\n      driver.current_url\n    end\n\n    ##\n    #\n    # Navigate to the given URL. The URL can either be a relative URL or an absolute URL\n    # The behaviour of either depends on the driver.\n    #\n    #     session.visit('/foo')\n    #     session.visit('http://google.com')\n    #\n    # For drivers which can run against an external application, such as the selenium driver\n    # giving an absolute URL will navigate to that page. This allows testing applications\n    # running on remote servers. For these drivers, setting {Capybara.configure app_host} will make the\n    # remote server the default. For example:\n    #\n    #     Capybara.app_host = 'http://google.com'\n    #     session.visit('/') # visits the google homepage\n    #\n    # If {Capybara.configure always_include_port} is set to `true` and this session is running against\n    # a rack application, then the port that the rack application is running on will automatically\n    # be inserted into the URL. Supposing the app is running on port `4567`, doing something like:\n    #\n    #     visit(\"http://google.com/test\")\n    #\n    # Will actually navigate to `http://google.com:4567/test`.\n    #\n    # @param [#to_s] visit_uri     The URL to navigate to. The parameter will be cast to a String.\n    #\n    def visit(visit_uri)\n      raise_server_error!\n      @touched = true\n\n      visit_uri = ::Addressable::URI.parse(visit_uri.to_s)\n      base_uri = ::Addressable::URI.parse(config.app_host || server_url)\n\n      if base_uri && [nil, 'http', 'https'].include?(visit_uri.scheme)\n        if visit_uri.relative?\n          visit_uri_parts = visit_uri.to_hash.compact\n\n          # Useful to people deploying to a subdirectory\n          # and/or single page apps where only the url fragment changes\n          visit_uri_parts[:path] = base_uri.path + visit_uri.path\n\n          visit_uri = base_uri.merge(visit_uri_parts)\n        end\n        adjust_server_port(visit_uri)\n      end\n\n      driver.visit(visit_uri.to_s)\n    end\n\n    ##\n    #\n    # Refresh the page.\n    #\n    def refresh\n      raise_server_error!\n      driver.refresh\n    end\n\n    ##\n    #\n    # Move back a single entry in the browser's history.\n    #\n    def go_back\n      driver.go_back\n    end\n\n    ##\n    #\n    # Move forward a single entry in the browser's history.\n    #\n    def go_forward\n      driver.go_forward\n    end\n\n    ##\n    # @!method send_keys\n    #   @see Capybara::Node::Element#send_keys\n    #\n    def send_keys(...)\n      driver.send_keys(...)\n    end\n\n    ##\n    #\n    # Returns the element with focus.\n    #\n    # Not supported by Rack Test\n    #\n    def active_element\n      Capybara::Queries::ActiveElementQuery.new.resolve_for(self)[0].tap(&:allow_reload!)\n    end\n\n    ##\n    #\n    # Executes the given block within the context of a node. {#within} takes the\n    # same options as {Capybara::Node::Finders#find #find}, as well as a block. For the duration of the\n    # block, any command to Capybara will be handled as though it were scoped\n    # to the given element.\n    #\n    #     within(:xpath, './/div[@id=\"delivery-address\"]') do\n    #       fill_in('Street', with: '12 Main Street')\n    #     end\n    #\n    # Just as with `#find`, if multiple elements match the selector given to\n    # {#within}, an error will be raised, and just as with `#find`, this\n    # behaviour can be controlled through the `:match` and `:exact` options.\n    #\n    # It is possible to omit the first parameter, in that case, the selector is\n    # assumed to be of the type set in {Capybara.configure default_selector}.\n    #\n    #     within('div#delivery-address') do\n    #       fill_in('Street', with: '12 Main Street')\n    #     end\n    #\n    # Note that a lot of uses of {#within} can be replaced more succinctly with\n    # chaining:\n    #\n    #     find('div#delivery-address').fill_in('Street', with: '12 Main Street')\n    #\n    # @overload within(*find_args)\n    #   @param (see Capybara::Node::Finders#all)\n    #\n    # @overload within(a_node)\n    #   @param [Capybara::Node::Base] a_node   The node in whose scope the block should be evaluated\n    #\n    # @raise  [Capybara::ElementNotFound]      If the scope can't be found before time expires\n    #\n    def within(*args, **kw_args)\n      new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args, **kw_args)\n      begin\n        scopes.push(new_scope)\n        yield new_scope if block_given?\n      ensure\n        scopes.pop\n      end\n    end\n    alias_method :within_element, :within\n\n    ##\n    #\n    # Execute the given block within the a specific fieldset given the id or legend of that fieldset.\n    #\n    # @param [String] locator    Id or legend of the fieldset\n    #\n    def within_fieldset(locator, &block)\n      within(:fieldset, locator, &block)\n    end\n\n    ##\n    #\n    # Execute the given block within the a specific table given the id or caption of that table.\n    #\n    # @param [String] locator    Id or caption of the table\n    #\n    def within_table(locator, &block)\n      within(:table, locator, &block)\n    end\n\n    ##\n    #\n    # Switch to the given frame.\n    #\n    # If you use this method you are responsible for making sure you switch back to the parent frame when done in the frame changed to.\n    # {#within_frame} is preferred over this method and should be used when possible.\n    # May not be supported by all drivers.\n    #\n    # @overload switch_to_frame(element)\n    #   @param [Capybara::Node::Element] element    iframe/frame element to switch to\n    # @overload switch_to_frame(location)\n    #   @param [Symbol] location relative location of the frame to switch to\n    #                            * :parent - the parent frame\n    #                            * :top - the top level document\n    #\n    def switch_to_frame(frame)\n      case frame\n      when Capybara::Node::Element\n        driver.switch_to_frame(frame)\n        scopes.push(:frame)\n      when :parent\n        if scopes.last != :frame\n          raise Capybara::ScopeError, \"`switch_to_frame(:parent)` cannot be called from inside a descendant frame's \" \\\n                                      '`within` block.'\n        end\n        scopes.pop\n        driver.switch_to_frame(:parent)\n      when :top\n        idx = scopes.index(:frame)\n        top_level_scopes = [:frame, nil]\n        if idx\n          if scopes.slice(idx..).any? { |scope| !top_level_scopes.include?(scope) }\n            raise Capybara::ScopeError, \"`switch_to_frame(:top)` cannot be called from inside a descendant frame's \" \\\n                                        '`within` block.'\n          end\n          scopes.slice!(idx..)\n          driver.switch_to_frame(:top)\n        end\n      else\n        raise ArgumentError, 'You must provide a frame element, :parent, or :top when calling switch_to_frame'\n      end\n    end\n\n    ##\n    #\n    # Execute the given block within the given iframe using given frame, frame name/id or index.\n    # May not be supported by all drivers.\n    #\n    # @overload within_frame(element)\n    #   @param [Capybara::Node::Element]  frame element\n    # @overload within_frame([kind = :frame], locator, **options)\n    #   @param [Symbol] kind      Optional selector type (:frame, :css, :xpath, etc.) - Defaults to :frame\n    #   @param [String] locator   The locator for the given selector kind.  For :frame this is the name/id of a frame/iframe element\n    # @overload within_frame(index)\n    #   @param [Integer] index         index of a frame (0 based)\n    def within_frame(*args, **kw_args)\n      switch_to_frame(_find_frame(*args, **kw_args))\n      begin\n        yield if block_given?\n      ensure\n        switch_to_frame(:parent)\n      end\n    end\n\n    ##\n    # @return [Capybara::Window]   current window\n    #\n    def current_window\n      Window.new(self, driver.current_window_handle)\n    end\n\n    ##\n    # Get all opened windows.\n    # The order of windows in returned array is not defined.\n    # The driver may sort windows by their creation time but it's not required.\n    #\n    # @return [Array<Capybara::Window>]   an array of all windows\n    #\n    def windows\n      driver.window_handles.map do |handle|\n        Window.new(self, handle)\n      end\n    end\n\n    ##\n    # Open a new window.\n    # The current window doesn't change as the result of this call.\n    # It should be switched to explicitly.\n    #\n    # @return [Capybara::Window]   window that has been opened\n    #\n    def open_new_window(kind = :tab)\n      window_opened_by do\n        if driver.method(:open_new_window).arity.zero?\n          driver.open_new_window\n        else\n          driver.open_new_window(kind)\n        end\n      end\n    end\n\n    ##\n    # Switch to the given window.\n    #\n    # @overload switch_to_window(&block)\n    #   Switches to the first window for which given block returns a value other than false or nil.\n    #   If window that matches block can't be found, the window will be switched back and {Capybara::WindowError} will be raised.\n    #   @example\n    #     window = switch_to_window { title == 'Page title' }\n    #   @raise [Capybara::WindowError]     if no window matches given block\n    # @overload switch_to_window(window)\n    #   @param window [Capybara::Window]   window that should be switched to\n    #   @raise [Capybara::Driver::Base#no_such_window_error] if nonexistent (e.g. closed) window was passed\n    #\n    # @return [Capybara::Window]         window that has been switched to\n    # @raise [Capybara::ScopeError]        if this method is invoked inside {#within} or\n    #   {#within_frame} methods\n    # @raise [ArgumentError]               if both or neither arguments were provided\n    #\n    def switch_to_window(window = nil, **options, &window_locator)\n      raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window && window_locator\n      raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !window_locator\n\n      unless scopes.last.nil?\n        raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from ' \\\n                                    '`within` or `within_frame` blocks.'\n      end\n\n      _switch_to_window(window, **options, &window_locator)\n    end\n\n    ##\n    # This method does the following:\n    #\n    # 1. Switches to the given window (it can be located by window instance/lambda/string).\n    # 2. Executes the given block (within window located at previous step).\n    # 3. Switches back (this step will be invoked even if an exception occurs at the second step).\n    #\n    # @overload within_window(window) { do_something }\n    #   @param window [Capybara::Window]       instance of {Capybara::Window} class\n    #     that will be switched to\n    #   @raise [driver#no_such_window_error] if nonexistent (e.g. closed) window was passed\n    # @overload within_window(proc_or_lambda) { do_something }\n    #   @param lambda [Proc]                  First window for which lambda\n    #     returns a value other than false or nil will be switched to.\n    #   @example\n    #     within_window(->{ page.title == 'Page title' }) { click_button 'Submit' }\n    #   @raise [Capybara::WindowError]         if no window matching lambda was found\n    #\n    # @raise [Capybara::ScopeError]        if this method is invoked inside {#within_frame} method\n    # @return                              value returned by the block\n    #\n    def within_window(window_or_proc)\n      original = current_window\n      scopes << nil\n      begin\n        case window_or_proc\n        when Capybara::Window\n          _switch_to_window(window_or_proc) unless original == window_or_proc\n        when Proc\n          _switch_to_window { window_or_proc.call }\n        else\n          raise ArgumentError, '`#within_window` requires a `Capybara::Window` instance or a lambda'\n        end\n\n        begin\n          yield if block_given?\n        ensure\n          _switch_to_window(original) unless original == window_or_proc\n        end\n      ensure\n        scopes.pop\n      end\n    end\n\n    ##\n    # Get the window that has been opened by the passed block.\n    # It will wait for it to be opened (in the same way as other Capybara methods wait).\n    # It's better to use this method than `windows.last`\n    # {https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html#h_note_10 as order of windows isn't defined in some drivers}.\n    #\n    # @overload window_opened_by(**options, &block)\n    #   @param options [Hash]\n    #   @option options [Numeric] :wait  maximum wait time. Defaults to {Capybara.configure default_max_wait_time}\n    #   @return [Capybara::Window]       the window that has been opened within a block\n    #   @raise [Capybara::WindowError]   if block passed to window hasn't opened window\n    #     or opened more than one window\n    #\n    def window_opened_by(**options)\n      old_handles = driver.window_handles\n      yield\n\n      synchronize_windows(options) do\n        opened_handles = (driver.window_handles - old_handles)\n        if opened_handles.size != 1\n          raise Capybara::WindowError, 'block passed to #window_opened_by ' \\\n                                       \"opened #{opened_handles.size} windows instead of 1\"\n        end\n        Window.new(self, opened_handles.first)\n      end\n    end\n\n    ##\n    #\n    # Execute the given script, not returning a result. This is useful for scripts that return\n    # complex objects, such as jQuery statements. {#execute_script} should be used over\n    # {#evaluate_script} whenever possible.\n    #\n    # @param [String] script   A string of JavaScript to execute\n    # @param args  Optional arguments that will be passed to the script. Driver support for this is optional and types of objects supported may differ between drivers\n    #\n    def execute_script(script, *args)\n      @touched = true\n      driver.execute_script(script, *driver_args(args))\n    end\n\n    ##\n    #\n    # Evaluate the given JavaScript and return the result. Be careful when using this with\n    # scripts that return complex objects, such as jQuery statements. {#execute_script} might\n    # be a better alternative.\n    #\n    # @param  [String] script   A string of JavaScript to evaluate\n    # @param           args     Optional arguments that will be passed to the script\n    # @return [Object]          The result of the evaluated JavaScript (may be driver specific)\n    #\n    def evaluate_script(script, *args)\n      @touched = true\n      result = driver.evaluate_script(script.strip, *driver_args(args))\n      element_script_result(result)\n    end\n\n    ##\n    #\n    # Evaluate the given JavaScript and obtain the result from a callback function which will be passed as the last argument to the script.\n    #\n    # @param  [String] script   A string of JavaScript to evaluate\n    # @param           args     Optional arguments that will be passed to the script\n    # @return [Object]          The result of the evaluated JavaScript (may be driver specific)\n    #\n    def evaluate_async_script(script, *args)\n      @touched = true\n      result = driver.evaluate_async_script(script, *driver_args(args))\n      element_script_result(result)\n    end\n\n    ##\n    #\n    # Execute the block, accepting a alert.\n    #\n    # @!macro modal_params\n    #   Expects a block whose actions will trigger the display modal to appear.\n    #   @example\n    #     $0 do\n    #       click_link('link that triggers appearance of system modal')\n    #     end\n    #   @overload $0(text, **options, &blk)\n    #     @param text [String, Regexp]  Text or regex to match against the text in the modal. If not provided any modal is matched.\n    #     @option options [Numeric] :wait  Maximum time to wait for the modal to appear after executing the block. Defaults to {Capybara.configure default_max_wait_time}.\n    #     @yield Block whose actions will trigger the system modal\n    #   @overload $0(**options, &blk)\n    #     @option options [Numeric] :wait  Maximum time to wait for the modal to appear after executing the block. Defaults to {Capybara.configure default_max_wait_time}.\n    #     @yield Block whose actions will trigger the system modal\n    #   @return [String]  the message shown in the modal\n    #   @raise [Capybara::ModalNotFound]  if modal dialog hasn't been found\n    #\n    def accept_alert(text = nil, **options, &blk)\n      accept_modal(:alert, text, options, &blk)\n    end\n\n    ##\n    #\n    # Execute the block, accepting a confirm.\n    #\n    # @macro modal_params\n    #\n    def accept_confirm(text = nil, **options, &blk)\n      accept_modal(:confirm, text, options, &blk)\n    end\n\n    ##\n    #\n    # Execute the block, dismissing a confirm.\n    #\n    # @macro modal_params\n    #\n    def dismiss_confirm(text = nil, **options, &blk)\n      dismiss_modal(:confirm, text, options, &blk)\n    end\n\n    ##\n    #\n    # Execute the block, accepting a prompt, optionally responding to the prompt.\n    #\n    # @macro modal_params\n    # @option options [String] :with   Response to provide to the prompt\n    #\n    def accept_prompt(text = nil, **options, &blk)\n      accept_modal(:prompt, text, options, &blk)\n    end\n\n    ##\n    #\n    # Execute the block, dismissing a prompt.\n    #\n    # @macro modal_params\n    #\n    def dismiss_prompt(text = nil, **options, &blk)\n      dismiss_modal(:prompt, text, options, &blk)\n    end\n\n    ##\n    #\n    # Save a snapshot of the page. If {Capybara.configure asset_host} is set it will inject `base` tag\n    # pointing to {Capybara.configure asset_host}.\n    #\n    # If invoked without arguments it will save file to {Capybara.configure save_path}\n    # and file will be given randomly generated filename. If invoked with a relative path\n    # the path will be relative to {Capybara.configure save_path}.\n    #\n    # @param [String] path  the path to where it should be saved\n    # @return [String]      the path to which the file was saved\n    #\n    def save_page(path = nil)\n      prepare_path(path, 'html').tap do |p_path|\n        File.write(p_path, Capybara::Helpers.inject_asset_host(body, host: config.asset_host), mode: 'wb')\n      end\n    end\n\n    ##\n    #\n    # Save a snapshot of the page and open it in a browser for inspection.\n    #\n    # If invoked without arguments it will save file to {Capybara.configure save_path}\n    # and file will be given randomly generated filename. If invoked with a relative path\n    # the path will be relative to {Capybara.configure save_path}.\n    #\n    # @param [String] path  the path to where it should be saved\n    #\n    def save_and_open_page(path = nil)\n      save_page(path).tap { |s_path| open_file(s_path) }\n    end\n\n    ##\n    #\n    # Save a screenshot of page.\n    #\n    # If invoked without arguments it will save file to {Capybara.configure save_path}\n    # and file will be given randomly generated filename. If invoked with a relative path\n    # the path will be relative to {Capybara.configure save_path}.\n    #\n    # @param [String] path    the path to where it should be saved\n    # @param [Hash] options   a customizable set of options\n    # @return [String]        the path to which the file was saved\n    def save_screenshot(path = nil, **options)\n      prepare_path(path, 'png').tap { |p_path| driver.save_screenshot(p_path, **options) }\n    end\n\n    ##\n    #\n    # Save a screenshot of the page and open it for inspection.\n    #\n    # If invoked without arguments it will save file to {Capybara.configure save_path}\n    # and file will be given randomly generated filename. If invoked with a relative path\n    # the path will be relative to {Capybara.configure save_path}.\n    #\n    # @param [String] path    the path to where it should be saved\n    # @param [Hash] options   a customizable set of options\n    #\n    def save_and_open_screenshot(path = nil, **options)\n      save_screenshot(path, **options).tap { |s_path| open_file(s_path) }\n    end\n\n    def document\n      @document ||= Capybara::Node::Document.new(self, driver)\n    end\n\n    NODE_METHODS.each do |method|\n      class_eval <<~METHOD, __FILE__, __LINE__ + 1\n        def #{method}(...)\n          @touched = true\n          current_scope.#{method}(...)\n        end\n      METHOD\n    end\n\n    DOCUMENT_METHODS.each do |method|\n      class_eval <<~METHOD, __FILE__, __LINE__ + 1\n        def #{method}(...)\n          document.#{method}(...)\n        end\n      METHOD\n    end\n\n    def inspect\n      %(#<Capybara::Session>)\n    end\n\n    def current_scope\n      scope = scopes.last\n      [nil, :frame].include?(scope) ? document : scope\n    end\n\n    ##\n    #\n    # Yield a block using a specific maximum wait time.\n    #\n    def using_wait_time(seconds, &block)\n      if Capybara.threadsafe\n        begin\n          previous_wait_time = config.default_max_wait_time\n          config.default_max_wait_time = seconds\n          yield\n        ensure\n          config.default_max_wait_time = previous_wait_time\n        end\n      else\n        Capybara.using_wait_time(seconds, &block)\n      end\n    end\n\n    ##\n    #\n    # Accepts a block to set the configuration options if {Capybara.configure threadsafe} is `true`. Note that some options only have an effect\n    # if set at initialization time, so look at the configuration block that can be passed to the initializer too.\n    #\n    def configure\n      raise 'Session configuration is only supported when Capybara.threadsafe == true' unless Capybara.threadsafe\n\n      yield config\n    end\n\n    def self.instance_created?\n      @@instance_created\n    end\n\n    def config\n      @config ||= if Capybara.threadsafe\n        Capybara.session_options.dup\n      else\n        Capybara::ReadOnlySessionConfig.new(Capybara.session_options)\n      end\n    end\n\n    def server_url\n      @server&.base_url\n    end\n\n  private\n\n    @@instance_created = false # rubocop:disable Style/ClassVars\n\n    def driver_args(args)\n      args.map { |arg| arg.is_a?(Capybara::Node::Element) ? arg.base : arg }\n    end\n\n    def accept_modal(type, text_or_options, options, &blk)\n      driver.accept_modal(type, **modal_options(text_or_options, **options), &blk)\n    end\n\n    def dismiss_modal(type, text_or_options, options, &blk)\n      driver.dismiss_modal(type, **modal_options(text_or_options, **options), &blk)\n    end\n\n    def modal_options(text = nil, **options)\n      options[:text] ||= text unless text.nil?\n      options[:wait] ||= config.default_max_wait_time\n      options\n    end\n\n    def open_file(path)\n      require 'launchy'\n      Launchy.open(path)\n    rescue LoadError\n      warn \"File saved to #{path}.\\nPlease install the launchy gem to open the file automatically.\"\n    end\n\n    def prepare_path(path, extension)\n      File.expand_path(path || default_fn(extension), config.save_path).tap do |p_path|\n        FileUtils.mkdir_p(File.dirname(p_path))\n      end\n    end\n\n    def default_fn(extension)\n      timestamp = Time.new.strftime('%Y%m%d%H%M%S')\n      \"capybara-#{timestamp}#{rand(10**10)}.#{extension}\"\n    end\n\n    def scopes\n      @scopes ||= [nil]\n    end\n\n    def element_script_result(arg)\n      case arg\n      when Array\n        arg.map { |subarg| element_script_result(subarg) }\n      when Hash\n        arg.transform_values! { |value| element_script_result(value) }\n      when Capybara::Driver::Node\n        Capybara::Node::Element.new(self, arg, nil, nil)\n      else\n        arg\n      end\n    end\n\n    def adjust_server_port(uri)\n      uri.port ||= @server.port if @server && config.always_include_port\n    end\n\n    def _find_frame(*args, **kw_args)\n      case args[0]\n      when Capybara::Node::Element\n        args[0]\n      when String, nil\n        find(:frame, *args, **kw_args)\n      when Symbol\n        find(*args, **kw_args)\n      when Integer\n        idx = args[0]\n        all(:frame, minimum: idx + 1)[idx]\n      else\n        raise TypeError\n      end\n    end\n\n    def _switch_to_window(window = nil, **options, &window_locator)\n      raise Capybara::ScopeError, 'Window cannot be switched inside a `within_frame` block' if scopes.include?(:frame)\n      raise Capybara::ScopeError, 'Window cannot be switched inside a `within` block' unless scopes.last.nil?\n\n      if window\n        driver.switch_to_window(window.handle)\n        window\n      else\n        synchronize_windows(options) do\n          original_window_handle = driver.current_window_handle\n          begin\n            _switch_to_window_by_locator(&window_locator)\n          rescue StandardError\n            driver.switch_to_window(original_window_handle)\n            raise\n          end\n        end\n      end\n    end\n\n    def _switch_to_window_by_locator\n      driver.window_handles.each do |handle|\n        driver.switch_to_window handle\n        return Window.new(self, handle) if yield\n      end\n      raise Capybara::WindowError, 'Could not find a window matching block/lambda'\n    end\n\n    def synchronize_windows(options, &block)\n      wait_time = Capybara::Queries::BaseQuery.wait(options, config.default_max_wait_time)\n      document.synchronize(wait_time, errors: [Capybara::WindowError], &block)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/fixtures/another_test_file.txt",
    "content": "ThisIsTheOtherTestFile\n"
  },
  {
    "path": "lib/capybara/spec/fixtures/no_extension",
    "content": "ThisFileHAsNoExtension"
  },
  {
    "path": "lib/capybara/spec/fixtures/test_file.txt",
    "content": "ThisIsTheTestFile"
  },
  {
    "path": "lib/capybara/spec/public/jquery-ui.js",
    "content": "/*! jQuery UI - v1.11.4 - 2015-03-11\n* http://jqueryui.com\n* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js\n* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */\n\n(function(e){\"function\"==typeof define&&define.amd?define([\"jquery\"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return\"area\"===r?(n=t.parentNode,a=n.name,t.href&&a&&\"map\"===n.nodeName.toLowerCase()?(o=e(\"img[usemap='#\"+a+\"']\")[0],!!o&&i(o)):!1):(/^(input|select|textarea|button|object)$/.test(r)?!t.disabled:\"a\"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return\"hidden\"===e.css(this,\"visibility\")}).length}function s(e){for(var t,i;e.length&&e[0]!==document;){if(t=e.css(\"position\"),(\"absolute\"===t||\"relative\"===t||\"fixed\"===t)&&(i=parseInt(e.css(\"zIndex\"),10),!isNaN(i)&&0!==i))return i;e=e.parent()}return 0}function n(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId=\"ui-datepicker-div\",this._inlineClass=\"ui-datepicker-inline\",this._appendClass=\"ui-datepicker-append\",this._triggerClass=\"ui-datepicker-trigger\",this._dialogClass=\"ui-datepicker-dialog\",this._disableClass=\"ui-datepicker-disabled\",this._unselectableClass=\"ui-datepicker-unselectable\",this._currentClass=\"ui-datepicker-current-day\",this._dayOverClass=\"ui-datepicker-days-cell-over\",this.regional=[],this.regional[\"\"]={closeText:\"Done\",prevText:\"Prev\",nextText:\"Next\",currentText:\"Today\",monthNames:[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"],monthNamesShort:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],dayNames:[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"],dayNamesShort:[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],dayNamesMin:[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"],weekHeader:\"Wk\",dateFormat:\"mm/dd/yy\",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:\"\"},this._defaults={showOn:\"focus\",showAnim:\"fadeIn\",showOptions:{},defaultDate:null,appendText:\"\",buttonText:\"...\",buttonImage:\"\",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:\"c-10:c+10\",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:\"+10\",minDate:null,maxDate:null,duration:\"fast\",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:\"\",altFormat:\"\",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[\"\"]),this.regional.en=e.extend(!0,{},this.regional[\"\"]),this.regional[\"en-US\"]=e.extend(!0,{},this.regional.en),this.dpDiv=a(e(\"<div id='\"+this._mainDivId+\"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\"))}function a(t){var i=\"button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a\";return t.delegate(i,\"mouseout\",function(){e(this).removeClass(\"ui-state-hover\"),-1!==this.className.indexOf(\"ui-datepicker-prev\")&&e(this).removeClass(\"ui-datepicker-prev-hover\"),-1!==this.className.indexOf(\"ui-datepicker-next\")&&e(this).removeClass(\"ui-datepicker-next-hover\")}).delegate(i,\"mouseover\",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(\".ui-datepicker-calendar\").find(\"a\").removeClass(\"ui-state-hover\"),e(this).addClass(\"ui-state-hover\"),-1!==this.className.indexOf(\"ui-datepicker-prev\")&&e(this).addClass(\"ui-datepicker-prev-hover\"),-1!==this.className.indexOf(\"ui-datepicker-next\")&&e(this).addClass(\"ui-datepicker-next-hover\"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger(\"change\")}}e.ui=e.ui||{},e.extend(e.ui,{version:\"1.11.4\",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css(\"position\"),s=\"absolute\"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&\"static\"===t.css(\"position\")?!1:n.test(t.css(\"overflow\")+t.css(\"overflow-y\")+t.css(\"overflow-x\"))}).eq(0);return\"fixed\"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id=\"ui-id-\"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\\d+$/.test(this.id)&&e(this).removeAttr(\"id\")})}}),e.extend(e.expr[\":\"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,\"tabindex\")))},tabbable:function(i){var s=e.attr(i,\"tabindex\"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e(\"<a>\").outerWidth(1).jquery||e.each([\"Width\",\"Height\"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,\"padding\"+this))||0,s&&(i-=parseFloat(e.css(t,\"border\"+this+\"Width\"))||0),a&&(i-=parseFloat(e.css(t,\"margin\"+this))||0)}),i}var n=\"Width\"===i?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn[\"inner\"+i]=function(t){return void 0===t?o[\"inner\"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+\"px\")})},e.fn[\"outer\"+i]=function(t,n){return\"number\"!=typeof t?o[\"outer\"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+\"px\")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e(\"<a>\").data(\"a-b\",\"a\").removeData(\"a-b\").data(\"a-b\")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return\"number\"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e=\"onselectstart\"in document.createElement(\"div\")?\"selectstart\":\"mousedown\";return function(){return this.bind(e+\".ui-disableSelection\",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(\".ui-disableSelection\")},zIndex:function(t){if(void 0!==t)return this.css(\"zIndex\",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css(\"position\"),(\"absolute\"===i||\"relative\"===i||\"fixed\"===i)&&(s=parseInt(n.css(\"zIndex\"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,\"events\"),s&&s.remove&&e(n).triggerHandler(\"remove\")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(\".\")[0];return t=t.split(\".\")[1],n=l+\"-\"+t,s||(s=i,i=e.Widget),e.expr[\":\"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+\".\"+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a=\"string\"==typeof n,o=u.call(arguments,1),r=this;return a?this.each(function(){var i,a=e.data(this,s);return\"instance\"===n?(r=a,!1):a?e.isFunction(a[n])&&\"_\"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error(\"no such method '\"+n+\"' for \"+t+\" widget instance\"):e.error(\"cannot call methods on \"+t+\" prior to initialization; \"+\"attempted to call method '\"+n+\"'\")}):(o.length&&(n=e.widget.extend.apply(null,[n].concat(o))),this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))})),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:\"widget\",widgetEventPrefix:\"\",defaultElement:\"<div>\",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace=\".\"+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger(\"create\",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr(\"aria-disabled\").removeClass(this.widgetFullName+\"-disabled \"+\"ui-state-disabled\"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass(\"ui-state-hover\"),this.focusable.removeClass(\"ui-state-focus\")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if(\"string\"==typeof t)if(o={},s=t.split(\".\"),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,\"disabled\"===e&&(this.widget().toggleClass(this.widgetFullName+\"-disabled\",!!t),t&&(this.hoverable.removeClass(\"ui-state-hover\"),this.focusable.removeClass(\"ui-state-focus\"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;\"boolean\"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass(\"ui-state-disabled\")?(\"string\"==typeof o?a[o]:o).apply(a,arguments):void 0}\"string\"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\\w:-]*)\\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||\"\").split(\" \").join(this.eventNamespace+\" \")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return(\"string\"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass(\"ui-state-hover\")},mouseleave:function(t){e(t.currentTarget).removeClass(\"ui-state-hover\")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass(\"ui-state-focus\")},focusout:function(t){e(t.currentTarget).removeClass(\"ui-state-focus\")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:\"fadeIn\",hide:\"fadeOut\"},function(t,i){e.Widget.prototype[\"_\"+t]=function(s,n,a){\"string\"==typeof n&&(n={effect:n});var o,r=n?n===!0||\"number\"==typeof n?i:n.effect||i:t;n=n||{},\"number\"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget(\"ui.mouse\",{version:\"1.11.4\",options:{cancel:\"input,textarea,button,select,option\",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind(\"mousedown.\"+this.widgetName,function(e){return t._mouseDown(e)}).bind(\"click.\"+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+\".preventClickEvent\")?(e.removeData(i.target,t.widgetName+\".preventClickEvent\"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind(\".\"+this.widgetName),this._mouseMoveDelegate&&this.document.unbind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).unbind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n=\"string\"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+\".preventClickEvent\")&&e.removeData(t.target,this.widgetName+\".preventClickEvent\"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).bind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind(\"mousemove.\"+this.widgetName,this._mouseMoveDelegate).unbind(\"mouseup.\"+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+\".preventClickEvent\",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\\+\\-]\\d+(\\.[\\d]+)?%?/,c=/^\\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e(\"<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>\"),a=s.children()[0];return e(\"body\").append(s),t=a.offsetWidth,s.css(\"overflow\",\"scroll\"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?\"\":t.element.css(\"overflow-x\"),s=t.isWindow||t.isDocument?\"\":t.element.css(\"overflow-y\"),n=\"scroll\"===i||\"auto\"===i&&t.width<t.element[0].scrollWidth,a=\"scroll\"===s||\"auto\"===s&&t.height<t.element[0].scrollHeight;return{width:a?e.position.scrollbarWidth():0,height:n?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var i=e(t||window),s=e.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s||n?i.width():i.outerWidth(),height:s||n?i.height():i.outerHeight()}}},e.fn.position=function(n){if(!n||!n.of)return f.apply(this,arguments);n=e.extend({},n);var p,m,g,v,y,b,_=e(n.of),x=e.position.getWithinInfo(n.within),w=e.position.getScrollInfo(x),k=(n.collision||\"flip\").split(\" \"),T={};return b=s(_),_[0].preventDefault&&(n.at=\"left top\"),m=b.width,g=b.height,v=b.offset,y=e.extend({},v),e.each([\"my\",\"at\"],function(){var e,t,i=(n[this]||\"\").split(\" \");1===i.length&&(i=l.test(i[0])?i.concat([\"center\"]):u.test(i[0])?[\"center\"].concat(i):[\"center\",\"center\"]),i[0]=l.test(i[0])?i[0]:\"center\",i[1]=u.test(i[1])?i[1]:\"center\",e=d.exec(i[0]),t=d.exec(i[1]),T[this]=[e?e[0]:0,t?t[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===k.length&&(k[1]=k[0]),\"right\"===n.at[0]?y.left+=m:\"center\"===n.at[0]&&(y.left+=m/2),\"bottom\"===n.at[1]?y.top+=g:\"center\"===n.at[1]&&(y.top+=g/2),p=t(T.at,m,g),y.left+=p[0],y.top+=p[1],this.each(function(){var s,l,u=e(this),d=u.outerWidth(),c=u.outerHeight(),f=i(this,\"marginLeft\"),b=i(this,\"marginTop\"),D=d+f+i(this,\"marginRight\")+w.width,S=c+b+i(this,\"marginBottom\")+w.height,M=e.extend({},y),C=t(T.my,u.outerWidth(),u.outerHeight());\"right\"===n.my[0]?M.left-=d:\"center\"===n.my[0]&&(M.left-=d/2),\"bottom\"===n.my[1]?M.top-=c:\"center\"===n.my[1]&&(M.top-=c/2),M.left+=C[0],M.top+=C[1],a||(M.left=h(M.left),M.top=h(M.top)),s={marginLeft:f,marginTop:b},e.each([\"left\",\"top\"],function(t,i){e.ui.position[k[t]]&&e.ui.position[k[t]][i](M,{targetWidth:m,targetHeight:g,elemWidth:d,elemHeight:c,collisionPosition:s,collisionWidth:D,collisionHeight:S,offset:[p[0]+C[0],p[1]+C[1]],my:n.my,at:n.at,within:x,elem:u})}),n.using&&(l=function(e){var t=v.left-M.left,i=t+m-d,s=v.top-M.top,a=s+g-c,h={target:{element:_,left:v.left,top:v.top,width:m,height:g},element:{element:u,left:M.left,top:M.top,width:d,height:c},horizontal:0>i?\"left\":t>0?\"right\":\"center\",vertical:0>a?\"top\":s>0?\"bottom\":\"middle\"};d>m&&m>r(t+i)&&(h.horizontal=\"center\"),c>g&&g>r(s+a)&&(h.vertical=\"middle\"),h.important=o(r(t),r(i))>o(r(s),r(a))?\"horizontal\":\"vertical\",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c=\"left\"===t.my[0]?-t.elemWidth:\"right\"===t.my[0]?t.elemWidth:0,p=\"left\"===t.at[0]?t.targetWidth:\"right\"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c=\"top\"===t.my[1],p=c?-t.elemHeight:\"bottom\"===t.my[1]?t.elemHeight:0,f=\"top\"===t.at[1]?t.targetHeight:\"bottom\"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName(\"body\")[0],h=document.createElement(\"div\");t=document.createElement(r?\"div\":\"body\"),s={visibility:\"hidden\",width:0,height:0,border:0,margin:0,background:\"none\"},r&&e.extend(s,{position:\"absolute\",left:\"-1000px\",top:\"-1000px\"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText=\"position: absolute; left: 10.7432222px;\",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML=\"\",i.removeChild(t)}()}(),e.ui.position,e.widget(\"ui.accordion\",{version:\"1.11.4\",options:{active:0,animate:{},collapsible:!1,event:\"click\",header:\"> li > :first-child,> :not(li):even\",heightStyle:\"auto\",icons:{activeHeader:\"ui-icon-triangle-1-s\",header:\"ui-icon-triangle-1-e\"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:\"hide\",borderBottomWidth:\"hide\",paddingTop:\"hide\",paddingBottom:\"hide\",height:\"hide\"},showProps:{borderTopWidth:\"show\",borderBottomWidth:\"show\",paddingTop:\"show\",paddingBottom:\"show\",height:\"show\"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass(\"ui-accordion ui-widget ui-helper-reset\").attr(\"role\",\"tablist\"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e(\"<span>\").addClass(\"ui-accordion-header-icon ui-icon \"+t.header).prependTo(this.headers),this.active.children(\".ui-accordion-header-icon\").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass(\"ui-accordion-icons\"))},_destroyIcons:function(){this.headers.removeClass(\"ui-accordion-icons\").children(\".ui-accordion-header-icon\").remove()},_destroy:function(){var e;this.element.removeClass(\"ui-accordion ui-widget ui-helper-reset\").removeAttr(\"role\"),this.headers.removeClass(\"ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top\").removeAttr(\"role\").removeAttr(\"aria-expanded\").removeAttr(\"aria-selected\").removeAttr(\"aria-controls\").removeAttr(\"tabIndex\").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass(\"ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled\").css(\"display\",\"\").removeAttr(\"role\").removeAttr(\"aria-hidden\").removeAttr(\"aria-labelledby\").removeUniqueId(),\"content\"!==this.options.heightStyle&&e.css(\"height\",\"\")},_setOption:function(e,t){return\"active\"===e?(this._activate(t),void 0):(\"event\"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),\"collapsible\"!==e||t||this.options.active!==!1||this._activate(0),\"icons\"===e&&(this._destroyIcons(),t&&this._createIcons()),\"disabled\"===e&&(this.element.toggleClass(\"ui-state-disabled\",!!t).attr(\"aria-disabled\",t),this.headers.add(this.headers.next()).toggleClass(\"ui-state-disabled\",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr(\"tabIndex\",-1),e(a).attr(\"tabIndex\",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(\".ui-state-disabled\").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass(\"ui-accordion-header ui-state-default ui-corner-all\"),this.panels=this.headers.next().addClass(\"ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom\").filter(\":not(.ui-accordion-content-active)\").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass(\"ui-accordion-header-active ui-state-active ui-corner-top\").removeClass(\"ui-corner-all\"),this.active.next().addClass(\"ui-accordion-content-active\").show(),this.headers.attr(\"role\",\"tab\").each(function(){var t=e(this),i=t.uniqueId().attr(\"id\"),s=t.next(),n=s.uniqueId().attr(\"id\");t.attr(\"aria-controls\",n),s.attr(\"aria-labelledby\",i)}).next().attr(\"role\",\"tabpanel\"),this.headers.not(this.active).attr({\"aria-selected\":\"false\",\"aria-expanded\":\"false\",tabIndex:-1}).next().attr({\"aria-hidden\":\"true\"}).hide(),this.active.length?this.active.attr({\"aria-selected\":\"true\",\"aria-expanded\":\"true\",tabIndex:0}).next().attr({\"aria-hidden\":\"false\"}):this.headers.eq(0).attr(\"tabIndex\",0),this._createIcons(),this._setupEvents(i.event),\"fill\"===s?(t=n.height(),this.element.siblings(\":visible\").each(function(){var i=e(this),s=i.css(\"position\");\"absolute\"!==s&&\"fixed\"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css(\"overflow\",\"auto\")):\"auto\"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css(\"height\",\"\").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return\"number\"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:\"_keydown\"};t&&e.each(t.split(\" \"),function(e,t){i[t]=\"_eventHandler\"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:\"_panelKeyDown\"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger(\"beforeActivate\",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass(\"ui-accordion-header-active ui-state-active\"),i.icons&&s.children(\".ui-accordion-header-icon\").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass(\"ui-corner-all\").addClass(\"ui-accordion-header-active ui-state-active ui-corner-top\"),i.icons&&n.children(\".ui-accordion-header-icon\").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass(\"ui-accordion-content-active\")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({\"aria-hidden\":\"true\"}),s.prev().attr({\"aria-selected\":\"false\",\"aria-expanded\":\"false\"}),i.length&&s.length?s.prev().attr({tabIndex:-1,\"aria-expanded\":\"false\"}):i.length&&this.headers.filter(function(){return 0===parseInt(e(this).attr(\"tabIndex\"),10)}).attr(\"tabIndex\",-1),i.attr(\"aria-hidden\",\"false\").prev().attr({\"aria-selected\":\"true\",\"aria-expanded\":\"true\",tabIndex:0})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.css(\"box-sizing\"),l=e.length&&(!t.length||e.index()<t.index()),u=this.options.animate||{},d=l&&u.down||u,c=function(){o._toggleComplete(i)};return\"number\"==typeof d&&(a=d),\"string\"==typeof d&&(n=d),n=n||d.easing||u.easing,a=a||d.duration||u.duration,t.length?e.length?(s=e.show().outerHeight(),t.animate(this.hideProps,{duration:a,easing:n,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(this.showProps,{duration:a,easing:n,complete:c,step:function(e,i){i.now=Math.round(e),\"height\"!==i.prop?\"content-box\"===h&&(r+=i.now):\"content\"!==o.options.heightStyle&&(i.now=Math.round(s-t.outerHeight()-r),r=0)}}),void 0):t.animate(this.hideProps,a,n,c):e.animate(this.showProps,a,n,c)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass(\"ui-accordion-content-active\").prev().removeClass(\"ui-corner-top\").addClass(\"ui-corner-all\"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger(\"activate\",null,e)}}),e.widget(\"ui.menu\",{version:\"1.11.4\",defaultElement:\"<ul>\",delay:300,options:{icons:{submenu:\"ui-icon-carat-1-e\"},items:\"> *\",menus:\"ul\",position:{my:\"left-1 top\",at:\"right top\"},role:\"menu\",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass(\"ui-menu ui-widget ui-widget-content\").toggleClass(\"ui-menu-icons\",!!this.element.find(\".ui-icon\").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass(\"ui-state-disabled\").attr(\"aria-disabled\",\"true\"),this._on({\"mousedown .ui-menu-item\":function(e){e.preventDefault()},\"click .ui-menu-item\":function(t){var i=e(t.target);!this.mouseHandled&&i.not(\".ui-state-disabled\").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(\".ui-menu\").length?this.expand(t):!this.element.is(\":focus\")&&e(this.document[0].activeElement).closest(\".ui-menu\").length&&(this.element.trigger(\"focus\",[!0]),this.active&&1===this.active.parents(\".ui-menu\").length&&clearTimeout(this.timer)))},\"mouseenter .ui-menu-item\":function(t){if(!this.previousFilter){var i=e(t.currentTarget);\ni.siblings(\".ui-state-active\").removeClass(\"ui-state-active\"),this.focus(t,i)}},mouseleave:\"collapseAll\",\"mouseleave .ui-menu\":\"collapseAll\",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:\"_keydown\"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr(\"aria-activedescendant\").find(\".ui-menu\").addBack().removeClass(\"ui-menu ui-widget ui-widget-content ui-menu-icons ui-front\").removeAttr(\"role\").removeAttr(\"tabIndex\").removeAttr(\"aria-labelledby\").removeAttr(\"aria-expanded\").removeAttr(\"aria-hidden\").removeAttr(\"aria-disabled\").removeUniqueId().show(),this.element.find(\".ui-menu-item\").removeClass(\"ui-menu-item\").removeAttr(\"role\").removeAttr(\"aria-disabled\").removeUniqueId().removeClass(\"ui-state-hover\").removeAttr(\"tabIndex\").removeAttr(\"role\").removeAttr(\"aria-haspopup\").children().each(function(){var t=e(this);t.data(\"ui-menu-submenu-carat\")&&t.remove()}),this.element.find(\".ui-menu-divider\").removeClass(\"ui-menu-divider ui-widget-content\")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move(\"first\",\"first\",t);break;case e.ui.keyCode.END:this._move(\"last\",\"last\",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(\".ui-state-disabled\")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||\"\",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(\".ui-menu-item\"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(\".ui-state-disabled\")||(this.active.is(\"[aria-haspopup='true']\")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass(\"ui-menu-icons\",!!this.element.find(\".ui-icon\").length),a.filter(\":not(.ui-menu)\").addClass(\"ui-menu ui-widget ui-widget-content ui-front\").hide().attr({role:this.options.role,\"aria-hidden\":\"true\",\"aria-expanded\":\"false\"}).each(function(){var t=e(this),i=t.parent(),s=e(\"<span>\").addClass(\"ui-menu-icon ui-icon \"+n).data(\"ui-menu-submenu-carat\",!0);i.attr(\"aria-haspopup\",\"true\").prepend(s),t.attr(\"aria-labelledby\",i.attr(\"id\"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(\".ui-menu-item\").each(function(){var t=e(this);s._isDivider(t)&&t.addClass(\"ui-widget-content ui-menu-divider\")}),i.not(\".ui-menu-item, .ui-menu-divider\").addClass(\"ui-menu-item\").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(\".ui-state-disabled\").attr(\"aria-disabled\",\"true\"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:\"menuitem\",listbox:\"option\"}[this.options.role]},_setOption:function(e,t){\"icons\"===e&&this.element.find(\".ui-menu-icon\").removeClass(this.options.icons.submenu).addClass(t.submenu),\"disabled\"===e&&this.element.toggleClass(\"ui-state-disabled\",!!t).attr(\"aria-disabled\",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&\"focus\"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass(\"ui-state-focus\").removeClass(\"ui-state-active\"),this.options.role&&this.element.attr(\"aria-activedescendant\",s.attr(\"id\")),this.active.parent().closest(\".ui-menu-item\").addClass(\"ui-state-active\"),e&&\"keydown\"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(\".ui-menu\"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger(\"focus\",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],\"borderTopWidth\"))||0,s=parseFloat(e.css(this.activeMenu[0],\"paddingTop\"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass(\"ui-state-focus\"),this.active=null,this._trigger(\"blur\",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),\"true\"===e.attr(\"aria-hidden\")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(\".ui-menu\").not(t.parents(\".ui-menu\")).hide().attr(\"aria-hidden\",\"true\"),t.show().removeAttr(\"aria-hidden\").attr(\"aria-expanded\",\"true\").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(\".ui-menu\"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(\".ui-menu\").hide().attr(\"aria-hidden\",\"true\").attr(\"aria-expanded\",\"false\").end().find(\".ui-state-active\").not(\".ui-state-focus\").removeClass(\"ui-state-active\")},_closeOnDocumentClick:function(t){return!e(t.target).closest(\".ui-menu\").length},_isDivider:function(e){return!/[^\\-\\u2014\\u2013\\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(\".ui-menu-item\",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(\".ui-menu \").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move(\"next\",\"first\",e)},previous:function(e){this._move(\"prev\",\"last\",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(\".ui-menu-item\").length},isLastItem:function(){return this.active&&!this.active.nextAll(\".ui-menu-item\").length},_move:function(e,t,i){var s;this.active&&(s=\"first\"===e||\"last\"===e?this.active[\"first\"===e?\"prevAll\":\"nextAll\"](\".ui-menu-item\").eq(-1):this.active[e+\"All\"](\".ui-menu-item\").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(\".ui-menu-item\").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?\"last\":\"first\"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(\".ui-menu-item\").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop(\"scrollHeight\")},select:function(t){this.active=this.active||e(t.target).closest(\".ui-menu-item\");var i={item:this.active};this.active.has(\".ui-menu\").length||this.collapseAll(t,!0),this._trigger(\"select\",t,i)},_filterMenuItems:function(t){var i=t.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,\"\\\\$&\"),s=RegExp(\"^\"+i,\"i\");return this.activeMenu.find(this.options.items).filter(\".ui-menu-item\").filter(function(){return s.test(e.trim(e(this).text()))})}}),e.widget(\"ui.autocomplete\",{version:\"1.11.4\",defaultElement:\"<input>\",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:\"left top\",at:\"left bottom\",collision:\"none\"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a=\"textarea\"===n,o=\"input\"===n;this.isMultiLine=a?!0:o?!1:this.element.prop(\"isContentEditable\"),this.valueMethod=this.element[a||o?\"val\":\"text\"],this.isNewMenu=!0,this.element.addClass(\"ui-autocomplete-input\").attr(\"autocomplete\",\"off\"),this._on(this.element,{keydown:function(n){if(this.element.prop(\"readOnly\"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move(\"previousPage\",n);break;case a.PAGE_DOWN:t=!0,this._move(\"nextPage\",n);break;case a.UP:t=!0,this._keyEvent(\"previous\",n);break;case a.DOWN:t=!0,this._keyEvent(\"next\",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(\":visible\")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(\":visible\"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move(\"previousPage\",s);break;case n.PAGE_DOWN:this._move(\"nextPage\",s);break;case n.UP:this._keyEvent(\"previous\",s);break;case n.DOWN:this._keyEvent(\"next\",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e(\"<ul>\").addClass(\"ui-autocomplete ui-front\").appendTo(this._appendTo()).menu({role:null}).hide().menu(\"instance\"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(\".ui-menu-item\").length||this._delay(function(){var t=this;this.document.one(\"mousedown\",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one(\"mousemove\",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data(\"ui-autocomplete-item\"),!1!==this._trigger(\"focus\",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr(\"aria-label\")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e(\"<div>\").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data(\"ui-autocomplete-item\"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger(\"select\",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e(\"<span>\",{role:\"status\",\"aria-live\":\"assertive\",\"aria-relevant\":\"additions\"}).addClass(\"ui-helper-hidden-accessible\").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr(\"autocomplete\")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass(\"ui-autocomplete-input\").removeAttr(\"autocomplete\"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),\"source\"===e&&this._initSource(),\"appendTo\"===e&&this.menu.element.appendTo(this._appendTo()),\"disabled\"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(\".ui-front\")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):\"string\"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:\"json\",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(\":visible\"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger(\"search\",t)!==!1?this._search(e):void 0},_search:function(e){this.pending++,this.element.addClass(\"ui-autocomplete-loading\"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass(\"ui-autocomplete-loading\")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger(\"response\",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger(\"open\")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(\":visible\")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger(\"close\",e))},_change:function(e){this.previous!==this._value()&&this._trigger(\"change\",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return\"string\"==typeof t?{label:t,value:t}:e.extend({},t,{label:t.label||t.value,value:t.value||t.label})})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width(\"\").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data(\"ui-autocomplete-item\",t)},_renderItem:function(t,i){return e(\"<li>\").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(\":visible\")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(\":visible\"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,\"\\\\$&\")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),\"i\");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget(\"ui.autocomplete\",e.ui.autocomplete,{options:{messages:{noResults:\"No search results.\",results:function(e){return e+(e>1?\" results are\":\" result is\")+\" available, use up and down arrow keys to navigate.\"}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e(\"<div>\").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete;var c,p=\"ui-button ui-widget ui-state-default ui-corner-all\",f=\"ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only\",m=function(){var t=e(this);setTimeout(function(){t.find(\":ui-button\").button(\"refresh\")},1)},g=function(t){var i=t.name,s=t.form,n=e([]);return i&&(i=i.replace(/'/g,\"\\\\'\"),n=s?e(s).find(\"[name='\"+i+\"'][type=radio]\"):e(\"[name='\"+i+\"'][type=radio]\",t.ownerDocument).filter(function(){return!this.form})),n};e.widget(\"ui.button\",{version:\"1.11.4\",defaultElement:\"<button>\",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest(\"form\").unbind(\"reset\"+this.eventNamespace).bind(\"reset\"+this.eventNamespace,m),\"boolean\"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop(\"disabled\"):this.element.prop(\"disabled\",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr(\"title\");var t=this,i=this.options,s=\"checkbox\"===this.type||\"radio\"===this.type,n=s?\"\":\"ui-state-active\";null===i.label&&(i.label=\"input\"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(p).attr(\"role\",\"button\").bind(\"mouseenter\"+this.eventNamespace,function(){i.disabled||this===c&&e(this).addClass(\"ui-state-active\")}).bind(\"mouseleave\"+this.eventNamespace,function(){i.disabled||e(this).removeClass(n)}).bind(\"click\"+this.eventNamespace,function(e){i.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass(\"ui-state-focus\")},blur:function(){this.buttonElement.removeClass(\"ui-state-focus\")}}),s&&this.element.bind(\"change\"+this.eventNamespace,function(){t.refresh()}),\"checkbox\"===this.type?this.buttonElement.bind(\"click\"+this.eventNamespace,function(){return i.disabled?!1:void 0}):\"radio\"===this.type?this.buttonElement.bind(\"click\"+this.eventNamespace,function(){if(i.disabled)return!1;e(this).addClass(\"ui-state-active\"),t.buttonElement.attr(\"aria-pressed\",\"true\");var s=t.element[0];g(s).not(s).map(function(){return e(this).button(\"widget\")[0]}).removeClass(\"ui-state-active\").attr(\"aria-pressed\",\"false\")}):(this.buttonElement.bind(\"mousedown\"+this.eventNamespace,function(){return i.disabled?!1:(e(this).addClass(\"ui-state-active\"),c=this,t.document.one(\"mouseup\",function(){c=null}),void 0)}).bind(\"mouseup\"+this.eventNamespace,function(){return i.disabled?!1:(e(this).removeClass(\"ui-state-active\"),void 0)}).bind(\"keydown\"+this.eventNamespace,function(t){return i.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass(\"ui-state-active\"),void 0)}).bind(\"keyup\"+this.eventNamespace+\" blur\"+this.eventNamespace,function(){e(this).removeClass(\"ui-state-active\")}),this.buttonElement.is(\"a\")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption(\"disabled\",i.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is(\"[type=checkbox]\")?\"checkbox\":this.element.is(\"[type=radio]\")?\"radio\":this.element.is(\"input\")?\"input\":\"button\",\"checkbox\"===this.type||\"radio\"===this.type?(e=this.element.parents().last(),t=\"label[for='\"+this.element.attr(\"id\")+\"']\",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass(\"ui-helper-hidden-accessible\"),i=this.element.is(\":checked\"),i&&this.buttonElement.addClass(\"ui-state-active\"),this.buttonElement.prop(\"aria-pressed\",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass(\"ui-helper-hidden-accessible\"),this.buttonElement.removeClass(p+\" ui-state-active \"+f).removeAttr(\"role\").removeAttr(\"aria-pressed\").html(this.buttonElement.find(\".ui-button-text\").html()),this.hasTitle||this.buttonElement.removeAttr(\"title\")},_setOption:function(e,t){return this._super(e,t),\"disabled\"===e?(this.widget().toggleClass(\"ui-state-disabled\",!!t),this.element.prop(\"disabled\",!!t),t&&(\"checkbox\"===this.type||\"radio\"===this.type?this.buttonElement.removeClass(\"ui-state-focus\"):this.buttonElement.removeClass(\"ui-state-focus ui-state-active\")),void 0):(this._resetButton(),void 0)},refresh:function(){var t=this.element.is(\"input, button\")?this.element.is(\":disabled\"):this.element.hasClass(\"ui-button-disabled\");t!==this.options.disabled&&this._setOption(\"disabled\",t),\"radio\"===this.type?g(this.element[0]).each(function(){e(this).is(\":checked\")?e(this).button(\"widget\").addClass(\"ui-state-active\").attr(\"aria-pressed\",\"true\"):e(this).button(\"widget\").removeClass(\"ui-state-active\").attr(\"aria-pressed\",\"false\")}):\"checkbox\"===this.type&&(this.element.is(\":checked\")?this.buttonElement.addClass(\"ui-state-active\").attr(\"aria-pressed\",\"true\"):this.buttonElement.removeClass(\"ui-state-active\").attr(\"aria-pressed\",\"false\"))},_resetButton:function(){if(\"input\"===this.type)return this.options.label&&this.element.val(this.options.label),void 0;var t=this.buttonElement.removeClass(f),i=e(\"<span></span>\",this.document[0]).addClass(\"ui-button-text\").html(this.options.label).appendTo(t.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push(\"ui-button-text-icon\"+(n?\"s\":s.primary?\"-primary\":\"-secondary\")),s.primary&&t.prepend(\"<span class='ui-button-icon-primary ui-icon \"+s.primary+\"'></span>\"),s.secondary&&t.append(\"<span class='ui-button-icon-secondary ui-icon \"+s.secondary+\"'></span>\"),this.options.text||(a.push(n?\"ui-button-icons-only\":\"ui-button-icon-only\"),this.hasTitle||t.attr(\"title\",e.trim(i)))):a.push(\"ui-button-text-only\"),t.addClass(a.join(\" \"))}}),e.widget(\"ui.buttonset\",{version:\"1.11.4\",options:{items:\"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)\"},_create:function(){this.element.addClass(\"ui-buttonset\")},_init:function(){this.refresh()},_setOption:function(e,t){\"disabled\"===e&&this.buttons.button(\"option\",e,t),this._super(e,t)},refresh:function(){var t=\"rtl\"===this.element.css(\"direction\"),i=this.element.find(this.options.items),s=i.filter(\":ui-button\");i.not(\":ui-button\").button(),s.button(\"refresh\"),this.buttons=i.map(function(){return e(this).button(\"widget\")[0]}).removeClass(\"ui-corner-all ui-corner-left ui-corner-right\").filter(\":first\").addClass(t?\"ui-corner-right\":\"ui-corner-left\").end().filter(\":last\").addClass(t?\"ui-corner-left\":\"ui-corner-right\").end().end()},_destroy:function(){this.element.removeClass(\"ui-buttonset\"),this.buttons.map(function(){return e(this).button(\"widget\")[0]}).removeClass(\"ui-corner-left ui-corner-right\").end().button(\"destroy\")}}),e.ui.button,e.extend(e.ui,{datepicker:{version:\"1.11.4\"}});var v;e.extend(n.prototype,{markerClassName:\"hasDatepicker\",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return r(this._defaults,e||{}),this},_attachDatepicker:function(t,i){var s,n,a;s=t.nodeName.toLowerCase(),n=\"div\"===s||\"span\"===s,t.id||(this.uuid+=1,t.id=\"dp\"+this.uuid),a=this._newInst(e(t),n),a.settings=e.extend({},i||{}),\"input\"===s?this._connectDatepicker(t,a):n&&this._inlineDatepicker(t,a)},_newInst:function(t,i){var s=t[0].id.replace(/([^A-Za-z0-9_\\-])/g,\"\\\\\\\\$1\");return{id:s,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?a(e(\"<div class='\"+this._inlineClass+\" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\")):this.dpDiv}},_connectDatepicker:function(t,i){var s=e(t);i.append=e([]),i.trigger=e([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),e.data(t,\"datepicker\",i),i.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,i){var s,n,a,o=this._get(i,\"appendText\"),r=this._get(i,\"isRTL\");i.append&&i.append.remove(),o&&(i.append=e(\"<span class='\"+this._appendClass+\"'>\"+o+\"</span>\"),t[r?\"before\":\"after\"](i.append)),t.unbind(\"focus\",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,\"showOn\"),(\"focus\"===s||\"both\"===s)&&t.focus(this._showDatepicker),(\"button\"===s||\"both\"===s)&&(n=this._get(i,\"buttonText\"),a=this._get(i,\"buttonImage\"),i.trigger=e(this._get(i,\"buttonImageOnly\")?e(\"<img/>\").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):e(\"<button type='button'></button>\").addClass(this._triggerClass).html(a?e(\"<img/>\").attr({src:a,alt:n,title:n}):n)),t[r?\"before\":\"after\"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,\"autoSize\")&&!e.inline){var t,i,s,n,a=new Date(2009,11,20),o=this._get(e,\"dateFormat\");o.match(/[DM]/)&&(t=function(e){for(i=0,s=0,n=0;e.length>n;n++)e[n].length>i&&(i=e[n].length,s=n);return s},a.setMonth(t(this._get(e,o.match(/MM/)?\"monthNames\":\"monthNamesShort\"))),a.setDate(t(this._get(e,o.match(/DD/)?\"dayNames\":\"dayNamesShort\"))+20-a.getDay())),e.input.attr(\"size\",this._formatDate(e,a).length)}},_inlineDatepicker:function(t,i){var s=e(t);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),e.data(t,\"datepicker\",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css(\"display\",\"block\"))},_dialogDatepicker:function(t,i,s,n,a){var o,h,l,u,d,c=this._dialogInst;return c||(this.uuid+=1,o=\"dp\"+this.uuid,this._dialogInput=e(\"<input type='text' id='\"+o+\"' style='position: absolute; top: -100px; width: 0px;'/>\"),this._dialogInput.keydown(this._doKeyDown),e(\"body\").append(this._dialogInput),c=this._dialogInst=this._newInst(this._dialogInput,!1),c.settings={},e.data(this._dialogInput[0],\"datepicker\",c)),r(c.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(c,i):i,this._dialogInput.val(i),this._pos=a?a.length?a:[a.pageX,a.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+u,l/2-150+d]),this._dialogInput.css(\"left\",this._pos[0]+20+\"px\").css(\"top\",this._pos[1]+\"px\"),c.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],\"datepicker\",c),this},_destroyDatepicker:function(t){var i,s=e(t),n=e.data(t,\"datepicker\");s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,\"datepicker\"),\"input\"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind(\"focus\",this._showDatepicker).unbind(\"keydown\",this._doKeyDown).unbind(\"keypress\",this._doKeyPress).unbind(\"keyup\",this._doKeyUp)):(\"div\"===i||\"span\"===i)&&s.removeClass(this.markerClassName).empty(),v===n&&(v=null))},_enableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,\"datepicker\");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),\"input\"===i?(t.disabled=!1,a.trigger.filter(\"button\").each(function(){this.disabled=!1}).end().filter(\"img\").css({opacity:\"1.0\",cursor:\"\"})):(\"div\"===i||\"span\"===i)&&(s=n.children(\".\"+this._inlineClass),s.children().removeClass(\"ui-state-disabled\"),s.find(\"select.ui-datepicker-month, select.ui-datepicker-year\").prop(\"disabled\",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,\"datepicker\");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),\"input\"===i?(t.disabled=!0,a.trigger.filter(\"button\").each(function(){this.disabled=!0}).end().filter(\"img\").css({opacity:\"0.5\",cursor:\"default\"})):(\"div\"===i||\"span\"===i)&&(s=n.children(\".\"+this._inlineClass),s.children().addClass(\"ui-state-disabled\"),s.find(\"select.ui-datepicker-month, select.ui-datepicker-year\").prop(\"disabled\",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,\"datepicker\")}catch(i){throw\"Missing instance data for this datepicker\"}},_optionDatepicker:function(t,i,s){var n,a,o,h,l=this._getInst(t);return 2===arguments.length&&\"string\"==typeof i?\"defaults\"===i?e.extend({},e.datepicker._defaults):l?\"all\"===i?e.extend({},l.settings):this._get(l,i):null:(n=i||{},\"string\"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),a=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(l,\"min\"),h=this._getMinMaxDate(l,\"max\"),r(l.settings,n),null!==o&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,o)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),\"disabled\"in n&&(n.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),l),this._autoSize(l),this._setDate(l,a),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,s,n,a=e.datepicker._getInst(t.target),o=!0,r=a.dpDiv.is(\".ui-datepicker-rtl\");if(a._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return n=e(\"td.\"+e.datepicker._dayOverClass+\":not(.\"+e.datepicker._currentClass+\")\",a.dpDiv),n[0]&&e.datepicker._selectDay(t.target,a.selectedMonth,a.selectedYear,n[0]),i=e.datepicker._get(a,\"onSelect\"),i?(s=e.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,\"stepBigMonths\"):-e.datepicker._get(a,\"stepMonths\"),\"M\");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,\"stepBigMonths\"):+e.datepicker._get(a,\"stepMonths\"),\"M\");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?1:-1,\"D\"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,\"stepBigMonths\"):-e.datepicker._get(a,\"stepMonths\"),\"M\");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,\"D\"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?-1:1,\"D\"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,\"stepBigMonths\"):+e.datepicker._get(a,\"stepMonths\"),\"M\");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,\"D\"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var i,s,n=e.datepicker._getInst(t.target);\nreturn e.datepicker._get(n,\"constrainInput\")?(i=e.datepicker._possibleChars(e.datepicker._get(n,\"dateFormat\")),s=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||\" \">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(t){var i,s=e.datepicker._getInst(t.target);if(s.input.val()!==s.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(s,\"dateFormat\"),s.input?s.input.val():null,e.datepicker._getFormatConfig(s)),i&&(e.datepicker._setDateFromField(s),e.datepicker._updateAlternate(s),e.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,\"input\"!==t.nodeName.toLowerCase()&&(t=e(\"input\",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,o,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,\"beforeShow\"),a=n?n.apply(t,[t,i]):{},a!==!1&&(r(i.settings,a),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=\"\"),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|=\"fixed\"===e(this).css(\"position\"),!o}),h={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:\"absolute\",display:\"block\",top:\"-1000px\"}),e.datepicker._updateDatepicker(i),h=e.datepicker._checkOffset(i,h,o),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?\"static\":o?\"fixed\":\"absolute\",display:\"none\",left:h.left+\"px\",top:h.top+\"px\"}),i.inline||(l=e.datepicker._get(i,\"showAnim\"),u=e.datepicker._get(i,\"duration\"),i.dpDiv.css(\"z-index\",s(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[l]?i.dpDiv.show(l,e.datepicker._get(i,\"showOptions\"),u):i.dpDiv[l||\"show\"](l?u:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,v=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var i,s=this._getNumberOfMonths(t),n=s[1],a=17,r=t.dpDiv.find(\".\"+this._dayOverClass+\" a\");r.length>0&&o.apply(r.get(0)),t.dpDiv.removeClass(\"ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4\").width(\"\"),n>1&&t.dpDiv.addClass(\"ui-datepicker-multi-\"+n).css(\"width\",a*n+\"em\"),t.dpDiv[(1!==s[0]||1!==s[1]?\"add\":\"remove\")+\"Class\"](\"ui-datepicker-multi\"),t.dpDiv[(this._get(t,\"isRTL\")?\"add\":\"remove\")+\"Class\"](\"ui-datepicker-rtl\"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find(\"select.ui-datepicker-year:first\").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(\":visible\")&&!e.input.is(\":disabled\")&&!e.input.is(\":focus\")},_checkOffset:function(t,i,s){var n=t.dpDiv.outerWidth(),a=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,r=t.input?t.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:e(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:e(document).scrollTop());return i.left-=this._get(t,\"isRTL\")?n-o:0,i.left-=s&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=s&&i.top===t.input.offset().top+r?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+r):0),i},_findPos:function(t){for(var i,s=this._getInst(t),n=this._get(s,\"isRTL\");t&&(\"hidden\"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[n?\"previousSibling\":\"nextSibling\"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,s,n,a,o=this._curInst;!o||t&&o!==e.data(t,\"datepicker\")||this._datepickerShowing&&(i=this._get(o,\"showAnim\"),s=this._get(o,\"duration\"),n=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,\"showOptions\"),s,n):o.dpDiv[\"slideDown\"===i?\"slideUp\":\"fadeIn\"===i?\"fadeOut\":\"hide\"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,\"onClose\"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():\"\",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:\"absolute\",left:\"0\",top:\"-100px\"}),e.blockUI&&(e.unblockUI(),e(\"body\").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(\".ui-datepicker-calendar\")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),s=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents(\"#\"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest(\".\"+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==s)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,s){var n=e(t),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+(\"M\"===s?this._get(a,\"showCurrentAtPos\"):0),s),this._updateDatepicker(a))},_gotoToday:function(t){var i,s=e(t),n=this._getInst(s[0]);this._get(n,\"gotoCurrent\")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(t,i,s){var n=e(t),a=this._getInst(n[0]);a[\"selected\"+(\"M\"===s?\"Month\":\"Year\")]=a[\"draw\"+(\"M\"===s?\"Month\":\"Year\")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(t,i,s,n){var a,o=e(t);e(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0])||(a=this._getInst(o[0]),a.selectedDay=a.currentDay=e(\"a\",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(t,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,\"\")},_selectDate:function(t,i){var s,n=e(t),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,\"onSelect\"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger(\"change\"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],\"object\"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,s,n,a=this._get(t,\"altField\");a&&(i=this._get(t,\"altFormat\")||this._get(t,\"dateFormat\"),s=this._getDate(t),n=this.formatDate(i,s,this._getFormatConfig(t)),e(a).each(function(){e(this).val(n)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,\"\"]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(t,i,s){if(null==t||null==i)throw\"Invalid arguments\";if(i=\"object\"==typeof i?\"\"+i:i+\"\",\"\"===i)return null;var n,a,o,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,u=\"string\"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,c=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,m=-1,g=-1,v=-1,y=-1,b=!1,_=function(e){var i=t.length>n+1&&t.charAt(n+1)===e;return i&&n++,i},x=function(e){var t=_(e),s=\"@\"===e?14:\"!\"===e?20:\"y\"===e&&t?4:\"o\"===e?3:2,n=\"y\"===e?s:1,a=RegExp(\"^\\\\d{\"+n+\",\"+s+\"}\"),o=i.substring(h).match(a);if(!o)throw\"Missing number at position \"+h;return h+=o[0].length,parseInt(o[0],10)},w=function(t,s,n){var a=-1,o=e.map(_(t)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,t){var s=t[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(a=t[0],h+=s.length,!1):void 0}),-1!==a)return a+1;throw\"Unknown name at position \"+h},k=function(){if(i.charAt(h)!==t.charAt(n))throw\"Unexpected literal at position \"+h;h++};for(n=0;t.length>n;n++)if(b)\"'\"!==t.charAt(n)||_(\"'\")?k():b=!1;else switch(t.charAt(n)){case\"d\":v=x(\"d\");break;case\"D\":w(\"D\",d,c);break;case\"o\":y=x(\"o\");break;case\"m\":g=x(\"m\");break;case\"M\":g=w(\"M\",p,f);break;case\"y\":m=x(\"y\");break;case\"@\":r=new Date(x(\"@\")),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case\"!\":r=new Date((x(\"!\")-this._ticksTo1970)/1e4),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case\"'\":_(\"'\")?k():b=!0;break;default:k()}if(i.length>h&&(o=i.substr(h),!/^\\s+/.test(o)))throw\"Extra/unparsed characters found in date: \"+o;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),y>-1)for(g=1,v=y;;){if(a=this._getDaysInMonth(m,g-1),a>=v)break;g++,v-=a}if(r=this._daylightSavingAdjust(new Date(m,g-1,v)),r.getFullYear()!==m||r.getMonth()+1!==g||r.getDate()!==v)throw\"Invalid date\";return r},ATOM:\"yy-mm-dd\",COOKIE:\"D, dd M yy\",ISO_8601:\"yy-mm-dd\",RFC_822:\"D, d M y\",RFC_850:\"DD, dd-M-y\",RFC_1036:\"D, d M y\",RFC_1123:\"D, d M yy\",RFC_2822:\"D, d M yy\",RSS:\"D, d M y\",TICKS:\"!\",TIMESTAMP:\"@\",W3C:\"yy-mm-dd\",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return\"\";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,o=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(t){var i=e.length>s+1&&e.charAt(s+1)===t;return i&&s++,i},l=function(e,t,i){var s=\"\"+t;if(h(e))for(;i>s.length;)s=\"0\"+s;return s},u=function(e,t,i,s){return h(e)?s[t]:i[t]},d=\"\",c=!1;if(t)for(s=0;e.length>s;s++)if(c)\"'\"!==e.charAt(s)||h(\"'\")?d+=e.charAt(s):c=!1;else switch(e.charAt(s)){case\"d\":d+=l(\"d\",t.getDate(),2);break;case\"D\":d+=u(\"D\",t.getDay(),n,a);break;case\"o\":d+=l(\"o\",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case\"m\":d+=l(\"m\",t.getMonth()+1,2);break;case\"M\":d+=u(\"M\",t.getMonth(),o,r);break;case\"y\":d+=h(\"y\")?t.getFullYear():(10>t.getYear()%100?\"0\":\"\")+t.getYear()%100;break;case\"@\":d+=t.getTime();break;case\"!\":d+=1e4*t.getTime()+this._ticksTo1970;break;case\"'\":h(\"'\")?d+=\"'\":c=!0;break;default:d+=e.charAt(s)}return d},_possibleChars:function(e){var t,i=\"\",s=!1,n=function(i){var s=e.length>t+1&&e.charAt(t+1)===i;return s&&t++,s};for(t=0;e.length>t;t++)if(s)\"'\"!==e.charAt(t)||n(\"'\")?i+=e.charAt(t):s=!1;else switch(e.charAt(t)){case\"d\":case\"m\":case\"y\":case\"@\":i+=\"0123456789\";break;case\"D\":case\"M\":return null;case\"'\":n(\"'\")?i+=\"'\":s=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,\"dateFormat\"),s=e.lastVal=e.input?e.input.val():null,n=this._getDefaultDate(e),a=n,o=this._getFormatConfig(e);try{a=this.parseDate(i,s,o)||n}catch(r){s=t?\"\":s}e.selectedDay=a.getDate(),e.drawMonth=e.selectedMonth=a.getMonth(),e.drawYear=e.selectedYear=a.getFullYear(),e.currentDay=s?a.getDate():0,e.currentMonth=s?a.getMonth():0,e.currentYear=s?a.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,\"defaultDate\"),new Date))},_determineDate:function(t,i,s){var n=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},a=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,\"dateFormat\"),i,e.datepicker._getFormatConfig(t))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,a=n.getFullYear(),o=n.getMonth(),r=n.getDate(),h=/([+\\-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||\"d\"){case\"d\":case\"D\":r+=parseInt(l[1],10);break;case\"w\":case\"W\":r+=7*parseInt(l[1],10);break;case\"m\":case\"M\":o+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o));break;case\"y\":case\"Y\":a+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o))}l=h.exec(i)}return new Date(a,o,r)},o=null==i||\"\"===i?s:\"string\"==typeof i?a(i):\"number\"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return o=o&&\"Invalid Date\"==\"\"+o?s:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var s=!t,n=e.selectedMonth,a=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),n===e.selectedMonth&&a===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(s?\"\":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&\"\"===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,\"stepMonths\"),s=\"#\"+t.id.replace(/\\\\\\\\/g,\"\\\\\");t.dpDiv.find(\"[data-handler]\").map(function(){var t={prev:function(){e.datepicker._adjustDate(s,-i,\"M\")},next:function(){e.datepicker._adjustDate(s,+i,\"M\")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(s)},selectDay:function(){return e.datepicker._selectDay(s,+this.getAttribute(\"data-month\"),+this.getAttribute(\"data-year\"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(s,this,\"M\"),!1},selectYear:function(){return e.datepicker._selectMonthYear(s,this,\"Y\"),!1}};e(this).bind(this.getAttribute(\"data-event\"),t[this.getAttribute(\"data-handler\")])})},_generateHTML:function(e){var t,i,s,n,a,o,r,h,l,u,d,c,p,f,m,g,v,y,b,_,x,w,k,T,D,S,M,C,N,A,P,I,H,z,F,E,O,j,W,L=new Date,R=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(e,\"isRTL\"),B=this._get(e,\"showButtonPanel\"),J=this._get(e,\"hideIfNoPrevNext\"),q=this._get(e,\"navigationAsDateFormat\"),K=this._getNumberOfMonths(e),V=this._get(e,\"showCurrentAtPos\"),U=this._get(e,\"stepMonths\"),Q=1!==K[0]||1!==K[1],G=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),X=this._getMinMaxDate(e,\"min\"),$=this._getMinMaxDate(e,\"max\"),Z=e.drawMonth-V,et=e.drawYear;if(0>Z&&(Z+=12,et--),$)for(t=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-K[0]*K[1]+1,$.getDate())),t=X&&X>t?X:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,\"prevText\"),i=q?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-U,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,-1,et,Z)?\"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='\"+i+\"'><span class='ui-icon ui-icon-circle-triangle-\"+(Y?\"e\":\"w\")+\"'>\"+i+\"</span></a>\":J?\"\":\"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='\"+i+\"'><span class='ui-icon ui-icon-circle-triangle-\"+(Y?\"e\":\"w\")+\"'>\"+i+\"</span></a>\",n=this._get(e,\"nextText\"),n=q?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z+U,1)),this._getFormatConfig(e)):n,a=this._canAdjustMonth(e,1,et,Z)?\"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='\"+n+\"'><span class='ui-icon ui-icon-circle-triangle-\"+(Y?\"w\":\"e\")+\"'>\"+n+\"</span></a>\":J?\"\":\"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='\"+n+\"'><span class='ui-icon ui-icon-circle-triangle-\"+(Y?\"w\":\"e\")+\"'>\"+n+\"</span></a>\",o=this._get(e,\"currentText\"),r=this._get(e,\"gotoCurrent\")&&e.currentDay?G:R,o=q?this.formatDate(o,r,this._getFormatConfig(e)):o,h=e.inline?\"\":\"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>\"+this._get(e,\"closeText\")+\"</button>\",l=B?\"<div class='ui-datepicker-buttonpane ui-widget-content'>\"+(Y?h:\"\")+(this._isInRange(e,r)?\"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>\"+o+\"</button>\":\"\")+(Y?\"\":h)+\"</div>\":\"\",u=parseInt(this._get(e,\"firstDay\"),10),u=isNaN(u)?0:u,d=this._get(e,\"showWeek\"),c=this._get(e,\"dayNames\"),p=this._get(e,\"dayNamesMin\"),f=this._get(e,\"monthNames\"),m=this._get(e,\"monthNamesShort\"),g=this._get(e,\"beforeShowDay\"),v=this._get(e,\"showOtherMonths\"),y=this._get(e,\"selectOtherMonths\"),b=this._getDefaultDate(e),_=\"\",w=0;K[0]>w;w++){for(k=\"\",this.maxRows=4,T=0;K[1]>T;T++){if(D=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),S=\" ui-corner-all\",M=\"\",Q){if(M+=\"<div class='ui-datepicker-group\",K[1]>1)switch(T){case 0:M+=\" ui-datepicker-group-first\",S=\" ui-corner-\"+(Y?\"right\":\"left\");break;case K[1]-1:M+=\" ui-datepicker-group-last\",S=\" ui-corner-\"+(Y?\"left\":\"right\");break;default:M+=\" ui-datepicker-group-middle\",S=\"\"}M+=\"'>\"}for(M+=\"<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix\"+S+\"'>\"+(/all|left/.test(S)&&0===w?Y?a:s:\"\")+(/all|right/.test(S)&&0===w?Y?s:a:\"\")+this._generateMonthYearHeader(e,Z,et,X,$,w>0||T>0,f,m)+\"</div><table class='ui-datepicker-calendar'><thead>\"+\"<tr>\",C=d?\"<th class='ui-datepicker-week-col'>\"+this._get(e,\"weekHeader\")+\"</th>\":\"\",x=0;7>x;x++)N=(x+u)%7,C+=\"<th scope='col'\"+((x+u+6)%7>=5?\" class='ui-datepicker-week-end'\":\"\")+\">\"+\"<span title='\"+c[N]+\"'>\"+p[N]+\"</span></th>\";for(M+=C+\"</tr></thead><tbody>\",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),P=(this._getFirstDayOfMonth(et,Z)-u+7)%7,I=Math.ceil((P+A)/7),H=Q?this.maxRows>I?this.maxRows:I:I,this.maxRows=H,z=this._daylightSavingAdjust(new Date(et,Z,1-P)),F=0;H>F;F++){for(M+=\"<tr>\",E=d?\"<td class='ui-datepicker-week-col'>\"+this._get(e,\"calculateWeek\")(z)+\"</td>\":\"\",x=0;7>x;x++)O=g?g.apply(e.input?e.input[0]:null,[z]):[!0,\"\"],j=z.getMonth()!==Z,W=j&&!y||!O[0]||X&&X>z||$&&z>$,E+=\"<td class='\"+((x+u+6)%7>=5?\" ui-datepicker-week-end\":\"\")+(j?\" ui-datepicker-other-month\":\"\")+(z.getTime()===D.getTime()&&Z===e.selectedMonth&&e._keyEvent||b.getTime()===z.getTime()&&b.getTime()===D.getTime()?\" \"+this._dayOverClass:\"\")+(W?\" \"+this._unselectableClass+\" ui-state-disabled\":\"\")+(j&&!v?\"\":\" \"+O[1]+(z.getTime()===G.getTime()?\" \"+this._currentClass:\"\")+(z.getTime()===R.getTime()?\" ui-datepicker-today\":\"\"))+\"'\"+(j&&!v||!O[2]?\"\":\" title='\"+O[2].replace(/'/g,\"&#39;\")+\"'\")+(W?\"\":\" data-handler='selectDay' data-event='click' data-month='\"+z.getMonth()+\"' data-year='\"+z.getFullYear()+\"'\")+\">\"+(j&&!v?\"&#xa0;\":W?\"<span class='ui-state-default'>\"+z.getDate()+\"</span>\":\"<a class='ui-state-default\"+(z.getTime()===R.getTime()?\" ui-state-highlight\":\"\")+(z.getTime()===G.getTime()?\" ui-state-active\":\"\")+(j?\" ui-priority-secondary\":\"\")+\"' href='#'>\"+z.getDate()+\"</a>\")+\"</td>\",z.setDate(z.getDate()+1),z=this._daylightSavingAdjust(z);M+=E+\"</tr>\"}Z++,Z>11&&(Z=0,et++),M+=\"</tbody></table>\"+(Q?\"</div>\"+(K[0]>0&&T===K[1]-1?\"<div class='ui-datepicker-row-break'></div>\":\"\"):\"\"),k+=M}_+=k}return _+=l,e._keyEvent=!1,_},_generateMonthYearHeader:function(e,t,i,s,n,a,o,r){var h,l,u,d,c,p,f,m,g=this._get(e,\"changeMonth\"),v=this._get(e,\"changeYear\"),y=this._get(e,\"showMonthAfterYear\"),b=\"<div class='ui-datepicker-title'>\",_=\"\";if(a||!g)_+=\"<span class='ui-datepicker-month'>\"+o[t]+\"</span>\";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,_+=\"<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>\",u=0;12>u;u++)(!h||u>=s.getMonth())&&(!l||n.getMonth()>=u)&&(_+=\"<option value='\"+u+\"'\"+(u===t?\" selected='selected'\":\"\")+\">\"+r[u]+\"</option>\");_+=\"</select>\"}if(y||(b+=_+(!a&&g&&v?\"\":\"&#xa0;\")),!e.yearshtml)if(e.yearshtml=\"\",a||!v)b+=\"<span class='ui-datepicker-year'>\"+i+\"</span>\";else{for(d=this._get(e,\"yearRange\").split(\":\"),c=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\\-].*/)?c+parseInt(e,10):parseInt(e,10);return isNaN(t)?c:t},f=p(d[0]),m=Math.max(f,p(d[1]||\"\")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,e.yearshtml+=\"<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>\";m>=f;f++)e.yearshtml+=\"<option value='\"+f+\"'\"+(f===i?\" selected='selected'\":\"\")+\">\"+f+\"</option>\";e.yearshtml+=\"</select>\",b+=e.yearshtml,e.yearshtml=null}return b+=this._get(e,\"yearSuffix\"),y&&(b+=(!a&&g&&v?\"\":\"&#xa0;\")+_),b+=\"</div>\"},_adjustInstDate:function(e,t,i){var s=e.drawYear+(\"Y\"===i?t:0),n=e.drawMonth+(\"M\"===i?t:0),a=Math.min(e.selectedDay,this._getDaysInMonth(s,n))+(\"D\"===i?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(s,n,a)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(\"M\"===i||\"Y\"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,\"min\"),s=this._getMinMaxDate(e,\"max\"),n=i&&i>t?i:t;return s&&n>s?s:n},_notifyChange:function(e){var t=this._get(e,\"onChangeMonthYear\");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,\"numberOfMonths\");return null==t?[1,1]:\"number\"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+\"Date\"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,s){var n=this._getNumberOfMonths(e),a=this._daylightSavingAdjust(new Date(i,s+(0>t?t:n[0]*n[1]),1));return 0>t&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(e,a)},_isInRange:function(e,t){var i,s,n=this._getMinMaxDate(e,\"min\"),a=this._getMinMaxDate(e,\"max\"),o=null,r=null,h=this._get(e,\"yearRange\");return h&&(i=h.split(\":\"),s=(new Date).getFullYear(),o=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\\-].*/)&&(o+=s),i[1].match(/[+\\-].*/)&&(r+=s)),(!n||t.getTime()>=n.getTime())&&(!a||t.getTime()<=a.getTime())&&(!o||t.getFullYear()>=o)&&(!r||r>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,\"shortYearCutoff\");return t=\"string\"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,\"dayNamesShort\"),dayNames:this._get(e,\"dayNames\"),monthNamesShort:this._get(e,\"monthNamesShort\"),monthNames:this._get(e,\"monthNames\")}},_formatDate:function(e,t,i,s){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var n=t?\"object\"==typeof t?t:this._daylightSavingAdjust(new Date(s,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,\"dateFormat\"),n,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e(\"#\"+e.datepicker._mainDivId).length&&e(\"body\").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return\"string\"!=typeof t||\"isDisabled\"!==t&&\"getDate\"!==t&&\"widget\"!==t?\"option\"===t&&2===arguments.length&&\"string\"==typeof arguments[1]?e.datepicker[\"_\"+t+\"Datepicker\"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){\"string\"==typeof t?e.datepicker[\"_\"+t+\"Datepicker\"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker[\"_\"+t+\"Datepicker\"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new n,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version=\"1.11.4\",e.datepicker,e.widget(\"ui.draggable\",e.ui.mouse,{version:\"1.11.4\",widgetEventPrefix:\"drag\",options:{addClasses:!0,appendTo:\"parent\",axis:!1,connectToSortable:!1,containment:!1,cursor:\"auto\",cursorAt:!1,grid:!1,handle:!1,helper:\"original\",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:\"default\",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:\"both\",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){\"original\"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass(\"ui-draggable\"),this.options.disabled&&this.element.addClass(\"ui-draggable-disabled\"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),\"handle\"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(\".ui-draggable-dragging\")?(this.destroyOnClear=!0,void 0):(this.element.removeClass(\"ui-draggable ui-draggable-dragging ui-draggable-disabled\"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(\".ui-resizable-handle\").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?\"iframe\":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e(\"<div>\").css(\"position\",\"absolute\").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&\"body\"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass(\"ui-draggable-dragging\"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css(\"position\"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return\"fixed\"===e(this).css(\"position\")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger(\"start\",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo(\"absolute\"),!i){var s=this._uiHash();if(this._trigger(\"drag\",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+\"px\",this.helper[0].style.top=this.position.top+\"px\",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),\"invalid\"===this.options.revert&&!s||\"valid\"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger(\"stop\",t)!==!1&&i._clear()}):this._trigger(\"stop\",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(\".ui-draggable-dragging\")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass(\"ui-draggable-handle\")},_removeHandleClassName:function(){this.handleElement.removeClass(\"ui-draggable-handle\")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):\"clone\"===i.helper?this.element.clone().removeAttr(\"id\"):this.element;return n.parents(\"body\").length||n.appendTo(\"parent\"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css(\"position\"))||n.css(\"position\",\"absolute\"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css(\"position\"))||(this.element[0].style.position=\"relative\")},_adjustOffsetFromHelper:function(t){\"string\"==typeof t&&(t=t.split(\" \")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),\"left\"in t&&(this.offset.click.left=t.left+this.margins.left),\"right\"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),\"top\"in t&&(this.offset.click.top=t.top+this.margins.top),\"bottom\"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return\"absolute\"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css(\"borderTopWidth\"),10)||0),left:t.left+(parseInt(this.offsetParent.css(\"borderLeftWidth\"),10)||0)}},_getRelativeOffset:function(){if(\"relative\"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css(\"top\"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css(\"left\"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css(\"marginLeft\"),10)||0,top:parseInt(this.element.css(\"marginTop\"),10)||0,right:parseInt(this.element.css(\"marginRight\"),10)||0,bottom:parseInt(this.element.css(\"marginBottom\"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?\"window\"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):\"document\"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):(\"parent\"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css(\"overflow\")),this.containment=[(parseInt(i.css(\"borderLeftWidth\"),10)||0)+(parseInt(i.css(\"paddingLeft\"),10)||0),(parseInt(i.css(\"borderTopWidth\"),10)||0)+(parseInt(i.css(\"paddingTop\"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css(\"borderRightWidth\"),10)||0)-(parseInt(i.css(\"paddingRight\"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css(\"borderBottomWidth\"),10)||0)-(parseInt(i.css(\"paddingBottom\"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)\n},_convertPositionTo:function(e,t){t||(t=this.position);var i=\"absolute\"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-(\"fixed\"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-(\"fixed\"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),\"y\"===o.axis&&(h=this.originalPageX),\"x\"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(\"fixed\"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(\"fixed\"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass(\"ui-draggable-dragging\"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){\"y\"!==this.options.axis&&\"auto\"!==this.helper.css(\"right\")&&(this.helper.width(this.helper.width()),this.helper.css(\"right\",\"auto\")),\"x\"!==this.options.axis&&\"auto\"!==this.helper.css(\"bottom\")&&(this.helper.height(this.helper.height()),this.helper.css(\"bottom\",\"auto\"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo(\"absolute\"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add(\"draggable\",\"connectToSortable\",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable(\"instance\");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger(\"activate\",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css(\"position\"),top:e.placeholder.css(\"top\"),left:e.placeholder.css(\"left\")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger(\"deactivate\",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,s._parent=i.helper.parent(),a.currentItem=i.helper.appendTo(a.element).data(\"ui-sortable-item\",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger(\"toSortable\",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger(\"out\",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger(\"fromSortable\",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add(\"draggable\",\"cursor\",{start:function(t,i,s){var n=e(\"body\"),a=s.options;n.css(\"cursor\")&&(a._cursor=n.css(\"cursor\")),n.css(\"cursor\",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e(\"body\").css(\"cursor\",n._cursor)}}),e.ui.plugin.add(\"draggable\",\"opacity\",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css(\"opacity\")&&(a._opacity=n.css(\"opacity\")),n.css(\"opacity\",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css(\"opacity\",n._opacity)}}),e.ui.plugin.add(\"draggable\",\"scroll\",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&\"HTML\"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&\"HTML\"!==o.tagName?(n.axis&&\"x\"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY<n.scrollSensitivity?o.scrollTop=a=o.scrollTop+n.scrollSpeed:t.pageY-s.overflowOffset.top<n.scrollSensitivity&&(o.scrollTop=a=o.scrollTop-n.scrollSpeed)),n.axis&&\"y\"===n.axis||(s.overflowOffset.left+o.offsetWidth-t.pageX<n.scrollSensitivity?o.scrollLeft=a=o.scrollLeft+n.scrollSpeed:t.pageX-s.overflowOffset.left<n.scrollSensitivity&&(o.scrollLeft=a=o.scrollLeft-n.scrollSpeed))):(n.axis&&\"x\"===n.axis||(t.pageY-e(r).scrollTop()<n.scrollSensitivity?a=e(r).scrollTop(e(r).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(r).scrollTop())<n.scrollSensitivity&&(a=e(r).scrollTop(e(r).scrollTop()+n.scrollSpeed))),n.axis&&\"y\"===n.axis||(t.pageX-e(r).scrollLeft()<n.scrollSensitivity?a=e(r).scrollLeft(e(r).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(r).scrollLeft())<n.scrollSensitivity&&(a=e(r).scrollLeft(e(r).scrollLeft()+n.scrollSpeed)))),a!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(s,t)}}),e.ui.plugin.add(\"draggable\",\"snap\",{start:function(t,i,s){var n=s.options;s.snapElements=[],e(n.snap.constructor!==String?n.snap.items||\":data(ui-draggable)\":n.snap).each(function(){var t=e(this),i=t.offset();this!==s.element[0]&&s.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:i.top,left:i.left})})},drag:function(t,i,s){var n,a,o,r,h,l,u,d,c,p,f=s.options,m=f.snapTolerance,g=i.offset.left,v=g+s.helperProportions.width,y=i.offset.top,b=y+s.helperProportions.height;for(c=s.snapElements.length-1;c>=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):(\"inner\"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo(\"relative\",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo(\"relative\",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo(\"relative\",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo(\"relative\",{top:0,left:l}).left)),p=n||a||o||r,\"outer\"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo(\"relative\",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo(\"relative\",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo(\"relative\",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo(\"relative\",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add(\"draggable\",\"stack\",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css(\"zIndex\"),10)||0)-(parseInt(e(i).css(\"zIndex\"),10)||0)});o.length&&(n=parseInt(e(o[0]).css(\"zIndex\"),10)||0,e(o).each(function(t){e(this).css(\"zIndex\",n+t)}),this.css(\"zIndex\",n+o.length))}}),e.ui.plugin.add(\"draggable\",\"zIndex\",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css(\"zIndex\")&&(a._zIndex=n.css(\"zIndex\")),n.css(\"zIndex\",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css(\"zIndex\",n._zIndex)}}),e.ui.draggable,e.widget(\"ui.resizable\",e.ui.mouse,{version:\"1.11.4\",widgetEventPrefix:\"resize\",options:{alsoResize:!1,animate:!1,animateDuration:\"slow\",animateEasing:\"swing\",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:\"e,s,se\",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if(\"hidden\"===e(t).css(\"overflow\"))return!1;var s=i&&\"left\"===i?\"scrollLeft\":\"scrollTop\",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass(\"ui-resizable\"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||\"ui-resizable-helper\":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(e(\"<div class='ui-wrapper' style='overflow: hidden;'></div>\").css({position:this.element.css(\"position\"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css(\"top\"),left:this.element.css(\"left\")})),this.element=this.element.parent().data(\"ui-resizable\",this.element.resizable(\"instance\")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css(\"marginLeft\"),marginTop:this.originalElement.css(\"marginTop\"),marginRight:this.originalElement.css(\"marginRight\"),marginBottom:this.originalElement.css(\"marginBottom\")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css(\"resize\"),this.originalElement.css(\"resize\",\"none\"),this._proportionallyResizeElements.push(this.originalElement.css({position:\"static\",zoom:1,display:\"block\"})),this.originalElement.css({margin:this.originalElement.css(\"margin\")}),this._proportionallyResize()),this.handles=r.handles||(e(\".ui-resizable-handle\",this.element).length?{n:\".ui-resizable-n\",e:\".ui-resizable-e\",s:\".ui-resizable-s\",w:\".ui-resizable-w\",se:\".ui-resizable-se\",sw:\".ui-resizable-sw\",ne:\".ui-resizable-ne\",nw:\".ui-resizable-nw\"}:\"e,s,se\"),this._handles=e(),this.handles.constructor===String)for(\"all\"===this.handles&&(this.handles=\"n,e,s,w,se,sw,ne,nw\"),t=this.handles.split(\",\"),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a=\"ui-resizable-\"+s,n=e(\"<div class='ui-resizable-handle \"+a+\"'></div>\"),n.css({zIndex:r.zIndex}),\"se\"===s&&n.addClass(\"ui-icon ui-icon-gripsmall-diagonal-se\"),this.handles[s]=\".ui-resizable-\"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=e(this.handles[i]),this._on(this.handles[i],{mousedown:o._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=[\"padding\",/ne|nw|n/.test(i)?\"Top\":/se|sw|s/.test(i)?\"Bottom\":/^e$/.test(i)?\"Right\":\"Left\"].join(\"\"),t.css(n,a),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(\".ui-resizable-handle\")),this._handles.disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:\"se\")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass(\"ui-resizable-autohide\").mouseenter(function(){r.disabled||(e(this).removeClass(\"ui-resizable-autohide\"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass(\"ui-resizable-autohide\"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass(\"ui-resizable ui-resizable-disabled ui-resizable-resizing\").removeData(\"resizable\").removeData(\"ui-resizable\").unbind(\".resizable\").find(\".ui-resizable-handle\").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css(\"position\"),width:t.outerWidth(),height:t.outerHeight(),top:t.css(\"top\"),left:t.css(\"left\")}).insertAfter(t),t.remove()),this.originalElement.css(\"resize\",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css(\"left\")),s=this._num(this.helper.css(\"top\")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=\"number\"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(\".ui-resizable-\"+this.axis).css(\"cursor\"),e(\"body\").css(\"cursor\",\"auto\"===n?this.axis+\"-resize\":n),o.addClass(\"ui-resizable-resizing\"),this._propagate(\"start\",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate(\"resize\",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger(\"resize\",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],\"left\")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css(\"left\"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css(\"top\"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e(\"body\").css(\"cursor\",\"auto\"),this.element.removeClass(\"ui-resizable-resizing\"),this._propagate(\"stop\",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+\"px\"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+\"px\"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+\"px\"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+\"px\"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),\"sw\"===s&&(e.left=t.left+(i.width-e.width),e.top=null),\"nw\"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidth<e.width,n=this._isNumber(e.height)&&t.maxHeight&&t.maxHeight<e.height,a=this._isNumber(e.width)&&t.minWidth&&t.minWidth>e.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css(\"borderTopWidth\"),e.css(\"borderRightWidth\"),e.css(\"borderBottomWidth\"),e.css(\"borderLeftWidth\")],n=[e.css(\"paddingTop\"),e.css(\"paddingRight\"),e.css(\"paddingBottom\"),e.css(\"paddingLeft\")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e(\"<div style='overflow:hidden;'></div>\"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:\"absolute\",left:this.elementOffset.left+\"px\",top:this.elementOffset.top+\"px\",zIndex:++i.zIndex}),this.helper.appendTo(\"body\").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),\"resize\"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add(\"resizable\",\"animate\",{stop:function(t){var i=e(this).resizable(\"instance\"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],\"left\")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css(\"left\"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css(\"top\"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css(\"width\"),10),height:parseInt(i.element.css(\"height\"),10),top:parseInt(i.element.css(\"top\"),10),left:parseInt(i.element.css(\"left\"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate(\"resize\",t)}})}}),e.ui.plugin.add(\"resizable\",\"containment\",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable(\"instance\"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e([\"Top\",\"Right\",\"Left\",\"Bottom\"]).each(function(e,s){i[e]=h._num(t.css(\"padding\"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,\"left\")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable(\"instance\"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css(\"position\"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css(\"position\")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable(\"instance\"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css(\"position\"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css(\"position\"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add(\"resizable\",\"alsoResize\",{start:function(){var t=e(this).resizable(\"instance\"),i=t.options;e(i.alsoResize).each(function(){var t=e(this);t.data(\"ui-resizable-alsoresize\",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css(\"left\"),10),top:parseInt(t.css(\"top\"),10)})})},resize:function(t,i){var s=e(this).resizable(\"instance\"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0};e(n.alsoResize).each(function(){var t=e(this),s=e(this).data(\"ui-resizable-alsoresize\"),n={},a=t.parents(i.originalElement[0]).length?[\"width\",\"height\"]:[\"width\",\"height\",\"top\",\"left\"];e.each(a,function(e,t){var i=(s[t]||0)+(r[t]||0);i&&i>=0&&(n[t]=i||null)}),t.css(n)})},stop:function(){e(this).removeData(\"resizable-alsoresize\")}}),e.ui.plugin.add(\"resizable\",\"ghost\",{start:function(){var t=e(this).resizable(\"instance\"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:\"block\",position:\"relative\",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass(\"ui-resizable-ghost\").addClass(\"string\"==typeof i.ghost?i.ghost:\"\"),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable(\"instance\");t.ghost&&t.ghost.css({position:\"relative\",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable(\"instance\");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add(\"resizable\",\"grid\",{resize:function(){var t,i=e(this).resizable(\"instance\"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h=\"number\"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=l-t.width,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget(\"ui.dialog\",{version:\"1.11.4\",options:{appendTo:\"body\",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:\"Close\",dialogClass:\"\",draggable:!0,hide:null,height:\"auto\",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:\"center\",at:\"center\",of:window,collision:\"fit\",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css(\"top\",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr(\"title\"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr(\"title\").addClass(\"ui-dialog-content ui-widget-content\").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||\"body\").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().removeClass(\"ui-dialog-content ui-widget-content\").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr(\"title\",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,s=this;if(this._isOpen&&this._trigger(\"beforeClose\",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(\":focusable\").focus().length)try{i=this.document[0].activeElement,i&&\"body\"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger(\"close\",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,i){var s=!1,n=this.uiDialog.siblings(\".ui-front:visible\").map(function(){return+e(this).css(\"z-index\")}).get(),a=Math.max.apply(null,n);return a>=+this.uiDialog.css(\"z-index\")&&(this.uiDialog.css(\"z-index\",a+1),s=!0),s&&!i&&this._trigger(\"focus\",t),s},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css(\"z-index\",this.uiDialog.css(\"z-index\")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger(\"focus\")}),this._makeFocusTarget(),this._trigger(\"open\"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find(\"[autofocus]\")),e.length||(e=this.element.find(\":tabbable\")),e.length||(e=this.uiDialogButtonPane.find(\":tabbable\")),e.length||(e=this.uiDialogTitlebarClose.filter(\":tabbable\")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e(\"<div>\").addClass(\"ui-dialog ui-widget ui-widget-content ui-corner-all ui-front \"+this.options.dialogClass).hide().attr({tabIndex:-1,role:\"dialog\"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0;\nif(t.keyCode===e.ui.keyCode.TAB&&!t.isDefaultPrevented()){var i=this.uiDialog.find(\":tabbable\"),s=i.filter(\":first\"),n=i.filter(\":last\");t.target!==n[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==s[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){n.focus()}),t.preventDefault()):(this._delay(function(){s.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find(\"[aria-describedby]\").length||this.uiDialog.attr({\"aria-describedby\":this.element.uniqueId().attr(\"id\")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e(\"<div>\").addClass(\"ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix\").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(\".ui-dialog-titlebar-close\")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e(\"<button type='button'></button>\").button({label:this.options.closeText,icons:{primary:\"ui-icon-closethick\"},text:!1}).addClass(\"ui-dialog-titlebar-close\").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e(\"<span>\").uniqueId().addClass(\"ui-dialog-title\").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({\"aria-labelledby\":t.attr(\"id\")})},_title:function(e){this.options.title||e.html(\"&#160;\"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e(\"<div>\").addClass(\"ui-dialog-buttonpane ui-widget-content ui-helper-clearfix\"),this.uiButtonSet=e(\"<div>\").addClass(\"ui-dialog-buttonset\").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass(\"ui-dialog-buttons\"),void 0):(e.each(i,function(i,s){var n,a;s=e.isFunction(s)?{click:s,text:i}:s,s=e.extend({type:\"button\"},s),n=s.click,s.click=function(){n.apply(t.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,e(\"<button></button>\",s).button(a).appendTo(t.uiButtonSet)}),this.uiDialog.addClass(\"ui-dialog-buttons\"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:\".ui-dialog-content, .ui-dialog-titlebar-close\",handle:\".ui-dialog-titlebar\",containment:\"document\",start:function(s,n){e(this).addClass(\"ui-dialog-dragging\"),i._blockFrames(),i._trigger(\"dragStart\",s,t(n))},drag:function(e,s){i._trigger(\"drag\",e,t(s))},stop:function(n,a){var o=a.offset.left-i.document.scrollLeft(),r=a.offset.top-i.document.scrollTop();s.position={my:\"left top\",at:\"left\"+(o>=0?\"+\":\"\")+o+\" \"+\"top\"+(r>=0?\"+\":\"\")+r,of:i.window},e(this).removeClass(\"ui-dialog-dragging\"),i._unblockFrames(),i._trigger(\"dragStop\",n,t(a))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css(\"position\"),o=\"string\"==typeof n?n:\"n,e,s,w,se,sw,ne,nw\";this.uiDialog.resizable({cancel:\".ui-dialog-content\",containment:\"document\",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){e(this).addClass(\"ui-dialog-resizing\"),i._blockFrames(),i._trigger(\"resizeStart\",s,t(n))},resize:function(e,s){i._trigger(\"resize\",e,t(s))},stop:function(n,a){var o=i.uiDialog.offset(),r=o.left-i.document.scrollLeft(),h=o.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:\"left top\",at:\"left\"+(r>=0?\"+\":\"\")+r+\" \"+\"top\"+(h>=0?\"+\":\"\")+h,of:i.window},e(this).removeClass(\"ui-dialog-resizing\"),i._unblockFrames(),i._trigger(\"resizeStop\",n,t(a))}}).css(\"position\",a)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=e(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),i=e.inArray(this,t);-1!==i&&t.splice(i,1)},_trackingInstances:function(){var e=this.document.data(\"ui-dialog-instances\");return e||(e=[],this.document.data(\"ui-dialog-instances\",e)),e},_minHeight:function(){var e=this.options;return\"auto\"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(\":visible\");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};e.each(t,function(e,t){i._setOption(e,t),e in i.sizeRelatedOptions&&(s=!0),e in i.resizableRelatedOptions&&(n[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(\":data(ui-resizable)\")&&this.uiDialog.resizable(\"option\",n)},_setOption:function(e,t){var i,s,n=this.uiDialog;\"dialogClass\"===e&&n.removeClass(this.options.dialogClass).addClass(t),\"disabled\"!==e&&(this._super(e,t),\"appendTo\"===e&&this.uiDialog.appendTo(this._appendTo()),\"buttons\"===e&&this._createButtons(),\"closeText\"===e&&this.uiDialogTitlebarClose.button({label:\"\"+t}),\"draggable\"===e&&(i=n.is(\":data(ui-draggable)\"),i&&!t&&n.draggable(\"destroy\"),!i&&t&&this._makeDraggable()),\"position\"===e&&this._position(),\"resizable\"===e&&(s=n.is(\":data(ui-resizable)\"),s&&!t&&n.resizable(\"destroy\"),s&&\"string\"==typeof t&&n.resizable(\"option\",\"handles\",t),s||t===!1||this._makeResizable()),\"title\"===e&&this._title(this.uiDialogTitlebar.find(\".ui-dialog-title\")))},_size:function(){var e,t,i,s=this.options;this.element.show().css({width:\"auto\",minHeight:0,maxHeight:\"none\",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),e=this.uiDialog.css({height:\"auto\",width:s.width}).outerHeight(),t=Math.max(0,s.minHeight-e),i=\"number\"==typeof s.maxHeight?Math.max(0,s.maxHeight-e):\"none\",\"auto\"===s.height?this.element.css({minHeight:t,maxHeight:i,height:\"auto\"}):this.element.height(Math.max(0,s.height-e)),this.uiDialog.is(\":data(ui-resizable)\")&&this.uiDialog.resizable(\"option\",\"minHeight\",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find(\"iframe\").map(function(){var t=e(this);return e(\"<div>\").css({position:\"absolute\",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(\".ui-dialog\").length?!0:!!e(t.target).closest(\".ui-datepicker\").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data(\"ui-dialog-overlays\")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e(\"<div>\").addClass(\"ui-widget-overlay ui-front\").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:\"_keepFocus\"}),this.document.data(\"ui-dialog-overlays\",(this.document.data(\"ui-dialog-overlays\")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data(\"ui-dialog-overlays\")-1;e?this.document.data(\"ui-dialog-overlays\",e):this.document.unbind(\"focusin\").removeData(\"ui-dialog-overlays\"),this.overlay.remove(),this.overlay=null}}}),e.widget(\"ui.droppable\",{version:\"1.11.4\",widgetEventPrefix:\"drop\",options:{accept:\"*\",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:\"default\",tolerance:\"intersect\",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass(\"ui-droppable\")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass(\"ui-droppable ui-droppable-disabled\")},_setOption:function(t,i){if(\"accept\"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if(\"scope\"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger(\"activate\",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger(\"deactivate\",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger(\"over\",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger(\"out\",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(\":data(ui-droppable)\").not(\".ui-draggable-dragging\").each(function(){var i=e(this).droppable(\"instance\");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger(\"drop\",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case\"fit\":return a>=l&&d>=r&&o>=u&&c>=h;case\"intersect\":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case\"pointer\":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case\"touch\":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{\"default\":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(\":data(ui-droppable)\").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible=\"none\"!==a[s].element.css(\"display\"),a[s].visible&&(\"mousedown\"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil(\"body\").bind(\"scroll.droppable\",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?\"isout\":o&&!this.isover?\"isover\":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(\":data(ui-droppable)\").filter(function(){return e(this).droppable(\"instance\").options.scope===n}),a.length&&(s=e(a[0]).droppable(\"instance\"),s.greedyChild=\"isover\"===r)),s&&\"isover\"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this[\"isout\"===r?\"isover\":\"isout\"]=!1,this[\"isover\"===r?\"_over\":\"_out\"].call(this,i),s&&\"isout\"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil(\"body\").unbind(\"scroll.droppable\"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable;var y=\"ui-effects-\",b=e;e.effects={effect:{}},function(e,t){function i(e,t,i){var s=d[t.type]||{};return null==e?i||!t.def?null:t.def:(e=s.floor?~~e:parseFloat(e),isNaN(e)?t.def:s.mod?(e+s.mod)%s.mod:0>e?0:e>s.max?s.max:e)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(e,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||\"rgba\";return h?(o=s[l](h),s[u[l].cache]=o[u[l].cache],n=s._rgba=o._rgba,!1):t}),n.length?(\"0,0,0,0\"===n.join()&&e.extend(n,a.transparent),s):a[i]}function n(e,t,i){return i=(i+1)%1,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+6*(t-e)*(2/3-i):e}var a,o=\"backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor\",r=/^([\\-+])=\\s*(\\d+\\.?\\d*)/,h=[{re:/rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\\(\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\\(\\s*(\\d+(?:\\.\\d+)?)\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,space:\"hsla\",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],l=e.Color=function(t,i,s,n){return new e.Color.fn.parse(t,i,s,n)},u={rgba:{props:{red:{idx:0,type:\"byte\"},green:{idx:1,type:\"byte\"},blue:{idx:2,type:\"byte\"}}},hsla:{props:{hue:{idx:0,type:\"degrees\"},saturation:{idx:1,type:\"percent\"},lightness:{idx:2,type:\"percent\"}}}},d={\"byte\":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},c=l.support={},p=e(\"<p>\")[0],f=e.each;p.style.cssText=\"background-color:rgba(1,1,1,.5)\",c.rgba=p.style.backgroundColor.indexOf(\"rgba\")>-1,f(u,function(e,t){t.cache=\"_\"+e,t.props.alpha={idx:3,type:\"percent\",def:1}}),l.fn=e.extend(l.prototype,{parse:function(n,o,r,h){if(n===t)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=e(n).css(o),o=t);var d=this,c=e.type(n),p=this._rgba=[];return o!==t&&(n=[n,o,r,h],c=\"array\"),\"string\"===c?this.parse(s(n)||a._default):\"array\"===c?(f(u.rgba.props,function(e,t){p[t.idx]=i(n[t.idx],t)}),this):\"object\"===c?(n instanceof l?f(u,function(e,t){n[t.cache]&&(d[t.cache]=n[t.cache].slice())}):f(u,function(t,s){var a=s.cache;f(s.props,function(e,t){if(!d[a]&&s.to){if(\"alpha\"===e||null==n[e])return;d[a]=s.to(d._rgba)}d[a][t.idx]=i(n[e],t,!0)}),d[a]&&0>e.inArray(null,d[a].slice(0,3))&&(d[a][3]=1,s.from&&(d._rgba=s.from(d[a])))}),this):t},is:function(e){var i=l(e),s=!0,n=this;return f(u,function(e,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(e,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:t})),s}),s},_space:function(){var e=[],t=this;return f(u,function(i,s){t[s.cache]&&e.push(i)}),e.pop()},transition:function(e,t){var s=l(e),n=s._space(),a=u[n],o=0===this.alpha()?l(\"transparent\"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(e,n){var a=n.idx,o=r[a],l=s[a],u=d[n.type]||{};null!==l&&(null===o?h[a]=l:(u.mod&&(l-o>u.mod/2?o+=u.mod:o-l>u.mod/2&&(o-=u.mod)),h[a]=i((l-o)*t+o,n)))}),this[n](h)},blend:function(t){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(t)._rgba;return l(e.map(i,function(e,t){return(1-s)*n[t]+s*e}))},toRgbaString:function(){var t=\"rgba(\",i=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===i[3]&&(i.pop(),t=\"rgb(\"),t+i.join()+\")\"},toHslaString:function(){var t=\"hsla(\",i=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+\"%\"),e});return 1===i[3]&&(i.pop(),t=\"hsl(\"),t+i.join()+\")\"},toHexString:function(t){var i=this._rgba.slice(),s=i.pop();return t&&i.push(~~(255*s)),\"#\"+e.map(i,function(e){return e=(e||0).toString(16),1===e.length?\"0\"+e:e}).join(\"\")},toString:function(){return 0===this._rgba[3]?\"transparent\":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,u.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,i,s=e[0]/255,n=e[1]/255,a=e[2]/255,o=e[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,u=r+h,d=.5*u;return t=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=d?l/u:l/(2-u),[Math.round(t)%360,i,d,null==o?1:o]},u.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,i=e[1],s=e[2],a=e[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,t+1/3)),Math.round(255*n(r,o,t)),Math.round(255*n(r,o,t-1/3)),a]},f(u,function(s,n){var a=n.props,o=n.cache,h=n.to,u=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===t)return this[o].slice();var n,r=e.type(s),d=\"array\"===r||\"object\"===r?s:arguments,c=this[o].slice();return f(a,function(e,t){var s=d[\"object\"===r?e:t.idx];null==s&&(s=c[t.idx]),c[t.idx]=i(s,t)}),u?(n=l(u(c)),n[o]=c,n):l(c)},f(a,function(t,i){l.fn[t]||(l.fn[t]=function(n){var a,o=e.type(n),h=\"alpha\"===t?this._hsla?\"hsla\":\"rgba\":s,l=this[h](),u=l[i.idx];return\"undefined\"===o?u:(\"function\"===o&&(n=n.call(this,u),o=e.type(n)),null==n&&i.empty?this:(\"string\"===o&&(a=r.exec(n),a&&(n=u+parseFloat(a[2])*(\"+\"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(t){var i=t.split(\" \");f(i,function(t,i){e.cssHooks[i]={set:function(t,n){var a,o,r=\"\";if(\"transparent\"!==n&&(\"string\"!==e.type(n)||(a=s(n)))){if(n=l(a||n),!c.rgba&&1!==n._rgba[3]){for(o=\"backgroundColor\"===i?t.parentNode:t;(\"\"===r||\"transparent\"===r)&&o&&o.style;)try{r=e.css(o,\"backgroundColor\"),o=o.parentNode}catch(h){}n=n.blend(r&&\"transparent\"!==r?r:\"_default\")}n=n.toRgbaString()}try{t.style[i]=n}catch(h){}}},e.fx.step[i]=function(t){t.colorInit||(t.start=l(t.elem,i),t.end=l(t.end),t.colorInit=!0),e.cssHooks[i].set(t.elem,t.start.transition(t.end,t.pos))}})},l.hook(o),e.cssHooks.borderColor={expand:function(e){var t={};return f([\"Top\",\"Right\",\"Bottom\",\"Left\"],function(i,s){t[\"border\"+s+\"Color\"]=e}),t}},a=e.Color.names={aqua:\"#00ffff\",black:\"#000000\",blue:\"#0000ff\",fuchsia:\"#ff00ff\",gray:\"#808080\",green:\"#008000\",lime:\"#00ff00\",maroon:\"#800000\",navy:\"#000080\",olive:\"#808000\",purple:\"#800080\",red:\"#ff0000\",silver:\"#c0c0c0\",teal:\"#008080\",white:\"#ffffff\",yellow:\"#ffff00\",transparent:[null,null,null,0],_default:\"#ffffff\"}}(b),function(){function t(t){var i,s,n=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],\"string\"==typeof n[i]&&(a[e.camelCase(i)]=n[i]);else for(i in n)\"string\"==typeof n[i]&&(a[i]=n[i]);return a}function i(t,i){var s,a,o={};for(s in i)a=i[s],t[s]!==a&&(n[s]||(e.fx.step[s]||!isNaN(parseFloat(a)))&&(o[s]=a));return o}var s=[\"add\",\"remove\",\"toggle\"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each([\"borderLeftStyle\",\"borderRightStyle\",\"borderBottomStyle\",\"borderTopStyle\"],function(t,i){e.fx.step[i]=function(e){(\"none\"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(b.style(e.elem,i,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(n,a,o,r){var h=e.speed(a,o,r);return this.queue(function(){var a,o=e(this),r=o.attr(\"class\")||\"\",l=h.children?o.find(\"*\").addBack():o;l=l.map(function(){var i=e(this);return{el:i,start:t(this)}}),a=function(){e.each(s,function(e,t){n[t]&&o[t+\"Class\"](n[t])})},a(),l=l.map(function(){return this.end=t(this.el[0]),this.diff=i(this.start,this.end),this}),o.attr(\"class\",r),l=l.map(function(){var t=this,i=e.Deferred(),s=e.extend({},h,{queue:!1,complete:function(){i.resolve(t)}});return this.el.animate(this.diff,s),i.promise()}),e.when.apply(e,l.get()).done(function(){a(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,\"\")})}),h.complete.call(o[0])})})},e.fn.extend({addClass:function(t){return function(i,s,n,a){return s?e.effects.animateClass.call(this,{add:i},s,n,a):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(i,s,n,a){return arguments.length>1?e.effects.animateClass.call(this,{remove:i},s,n,a):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(i,s,n,a,o){return\"boolean\"==typeof s||void 0===s?n?e.effects.animateClass.call(this,s?{add:i}:{remove:i},n,a,o):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:i},s,n,a)}}(e.fn.toggleClass),switchClass:function(t,i,s,n,a){return e.effects.animateClass.call(this,{add:i,remove:t},s,n,a)}})}(),function(){function t(t,i,s,n){return e.isPlainObject(t)&&(i=t,t=t.effect),t={effect:t},null==i&&(i={}),e.isFunction(i)&&(n=i,s=null,i={}),(\"number\"==typeof i||e.fx.speeds[i])&&(n=s,s=i,i={}),e.isFunction(s)&&(n=s,s=null),i&&e.extend(t,i),s=s||i.duration,t.duration=e.fx.off?0:\"number\"==typeof s?s:s in e.fx.speeds?e.fx.speeds[s]:e.fx.speeds._default,t.complete=n||i.complete,t}function i(t){return!t||\"number\"==typeof t||e.fx.speeds[t]?!0:\"string\"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:\"object\"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:\"1.11.4\",save:function(e,t){for(var i=0;t.length>i;i++)null!==t[i]&&e.data(y+t[i],e[0].style[t[i]])},restore:function(e,t){var i,s;for(s=0;t.length>s;s++)null!==t[s]&&(i=e.data(y+t[s]),void 0===i&&(i=\"\"),e.css(t[s],i))},setMode:function(e,t){return\"toggle\"===t&&(t=e.is(\":hidden\")?\"show\":\"hide\"),t},getBaseline:function(e,t){var i,s;switch(e[0]){case\"top\":i=0;break;case\"middle\":i=.5;break;case\"bottom\":i=1;break;default:i=e[0]/t.height}switch(e[1]){case\"left\":s=0;break;case\"center\":s=.5;break;case\"right\":s=1;break;default:s=e[1]/t.width}return{x:s,y:i}},createWrapper:function(t){if(t.parent().is(\".ui-effects-wrapper\"))return t.parent();var i={width:t.outerWidth(!0),height:t.outerHeight(!0),\"float\":t.css(\"float\")},s=e(\"<div></div>\").addClass(\"ui-effects-wrapper\").css({fontSize:\"100%\",background:\"transparent\",border:\"none\",margin:0,padding:0}),n={width:t.width(),height:t.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return t.wrap(s),(t[0]===a||e.contains(t[0],a))&&e(a).focus(),s=t.parent(),\"static\"===t.css(\"position\")?(s.css({position:\"relative\"}),t.css({position:\"relative\"})):(e.extend(i,{position:t.css(\"position\"),zIndex:t.css(\"z-index\")}),e.each([\"top\",\"left\",\"bottom\",\"right\"],function(e,s){i[s]=t.css(s),isNaN(parseInt(i[s],10))&&(i[s]=\"auto\")}),t.css({position:\"relative\",top:0,left:0,right:\"auto\",bottom:\"auto\"})),t.css(n),s.css(i).show()},removeWrapper:function(t){var i=document.activeElement;return t.parent().is(\".ui-effects-wrapper\")&&(t.parent().replaceWith(t),(t[0]===i||e.contains(t[0],i))&&e(i).focus()),t},setTransition:function(t,i,s,n){return n=n||{},e.each(i,function(e,i){var a=t.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),e.fn.extend({effect:function(){function i(t){function i(){e.isFunction(a)&&a.call(n[0]),e.isFunction(t)&&t()}var n=e(this),a=s.complete,r=s.mode;(n.is(\":hidden\")?\"hide\"===r:\"show\"===r)?(n[r](),i()):o.call(n[0],s,i)}var s=t.apply(this,arguments),n=s.mode,a=s.queue,o=e.effects.effect[s.effect];return e.fx.off||!o?n?this[n](s.duration,s.complete):this.each(function(){s.complete&&s.complete.call(this)}):a===!1?this.each(i):this.queue(a||\"fx\",i)},show:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode=\"show\",this.effect.call(this,n)}}(e.fn.show),hide:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode=\"hide\",this.effect.call(this,n)}}(e.fn.hide),toggle:function(e){return function(s){if(i(s)||\"boolean\"==typeof s)return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode=\"toggle\",this.effect.call(this,n)}}(e.fn.toggle),cssUnit:function(t){var i=this.css(t),s=[];return e.each([\"em\",\"px\",\"%\",\"pt\"],function(e,t){i.indexOf(t)>0&&(s=[parseFloat(i),t])}),s}})}(),function(){var t={};e.each([\"Quad\",\"Cubic\",\"Quart\",\"Quint\",\"Expo\"],function(e,i){t[i]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,i=4;((t=Math.pow(2,--i))-1)/11>e;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,i){e.easing[\"easeIn\"+t]=i,e.easing[\"easeOut\"+t]=function(e){return 1-i(1-e)},e.easing[\"easeInOut\"+t]=function(e){return.5>e?i(2*e)/2:1-i(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,i){var s,n,a,o=e(this),r=/up|down|vertical/,h=/up|left|vertical|horizontal/,l=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"height\",\"width\"],u=e.effects.setMode(o,t.mode||\"hide\"),d=t.direction||\"up\",c=r.test(d),p=c?\"height\":\"width\",f=c?\"top\":\"left\",m=h.test(d),g={},v=\"show\"===u;o.parent().is(\".ui-effects-wrapper\")?e.effects.save(o.parent(),l):e.effects.save(o,l),o.show(),s=e.effects.createWrapper(o).css({overflow:\"hidden\"}),n=s[p](),a=parseFloat(s.css(f))||0,g[p]=v?n:0,m||(o.css(c?\"bottom\":\"right\",0).css(c?\"top\":\"left\",\"auto\").css({position:\"absolute\"}),g[f]=v?a:n+a),v&&(s.css(p,0),m||s.css(f,a+n)),s.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){\"hide\"===u&&o.hide(),e.effects.restore(o,l),e.effects.removeWrapper(o),i()}})},e.effects.effect.bounce=function(t,i){var s,n,a,o=e(this),r=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"height\",\"width\"],h=e.effects.setMode(o,t.mode||\"effect\"),l=\"hide\"===h,u=\"show\"===h,d=t.direction||\"up\",c=t.distance,p=t.times||5,f=2*p+(u||l?1:0),m=t.duration/f,g=t.easing,v=\"up\"===d||\"down\"===d?\"top\":\"left\",y=\"up\"===d||\"left\"===d,b=o.queue(),_=b.length;for((u||l)&&r.push(\"opacity\"),e.effects.save(o,r),o.show(),e.effects.createWrapper(o),c||(c=o[\"top\"===v?\"outerHeight\":\"outerWidth\"]()/3),u&&(a={opacity:1},a[v]=0,o.css(\"opacity\",0).css(v,y?2*-c:2*c).animate(a,m,g)),l&&(c/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(y?\"-=\":\"+=\")+c,o.animate(n,m,g).animate(a,m,g),c=l?2*c:c/2;l&&(n={opacity:0},n[v]=(y?\"-=\":\"+=\")+c,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}),_>1&&b.splice.apply(b,[1,0].concat(b.splice(_,f+1))),o.dequeue()},e.effects.effect.clip=function(t,i){var s,n,a,o=e(this),r=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"height\",\"width\"],h=e.effects.setMode(o,t.mode||\"hide\"),l=\"show\"===h,u=t.direction||\"vertical\",d=\"vertical\"===u,c=d?\"height\":\"width\",p=d?\"top\":\"left\",f={};e.effects.save(o,r),o.show(),s=e.effects.createWrapper(o).css({overflow:\"hidden\"}),n=\"IMG\"===o[0].tagName?s:o,a=n[c](),l&&(n.css(c,0),n.css(p,a/2)),f[c]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){l||o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}})},e.effects.effect.drop=function(t,i){var s,n=e(this),a=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"opacity\",\"height\",\"width\"],o=e.effects.setMode(n,t.mode||\"hide\"),r=\"show\"===o,h=t.direction||\"left\",l=\"up\"===h||\"down\"===h?\"top\":\"left\",u=\"up\"===h||\"left\"===h?\"pos\":\"neg\",d={opacity:r?1:0};e.effects.save(n,a),n.show(),e.effects.createWrapper(n),s=t.distance||n[\"top\"===l?\"outerHeight\":\"outerWidth\"](!0)/2,r&&n.css(\"opacity\",0).css(l,\"pos\"===u?-s:s),d[l]=(r?\"pos\"===u?\"+=\":\"-=\":\"pos\"===u?\"-=\":\"+=\")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){\"hide\"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.explode=function(t,i){function s(){b.push(this),b.length===d*c&&n()}function n(){p.css({visibility:\"visible\"}),e(b).remove(),m||p.hide(),i()}var a,o,r,h,l,u,d=t.pieces?Math.round(Math.sqrt(t.pieces)):3,c=d,p=e(this),f=e.effects.setMode(p,t.mode||\"hide\"),m=\"show\"===f,g=p.show().css(\"visibility\",\"hidden\").offset(),v=Math.ceil(p.outerWidth()/c),y=Math.ceil(p.outerHeight()/d),b=[];for(a=0;d>a;a++)for(h=g.top+a*y,u=a-(d-1)/2,o=0;c>o;o++)r=g.left+o*v,l=o-(c-1)/2,p.clone().appendTo(\"body\").wrap(\"<div></div>\").css({position:\"absolute\",visibility:\"visible\",left:-o*v,top:-a*y}).parent().addClass(\"ui-effects-explode\").css({position:\"absolute\",overflow:\"hidden\",width:v,height:y,left:r+(m?l*v:0),top:h+(m?u*y:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:u*y),opacity:m?1:0},t.duration||500,t.easing,s)},e.effects.effect.fade=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||\"toggle\");s.animate({opacity:n},{queue:!1,duration:t.duration,easing:t.easing,complete:i})},e.effects.effect.fold=function(t,i){var s,n,a=e(this),o=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"height\",\"width\"],r=e.effects.setMode(a,t.mode||\"hide\"),h=\"show\"===r,l=\"hide\"===r,u=t.size||15,d=/([0-9]+)%/.exec(u),c=!!t.horizFirst,p=h!==c,f=p?[\"width\",\"height\"]:[\"height\",\"width\"],m=t.duration/2,g={},v={};e.effects.save(a,o),a.show(),s=e.effects.createWrapper(a).css({overflow:\"hidden\"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],d&&(u=parseInt(d[1],10)/100*n[l?0:1]),h&&s.css(c?{height:0,width:u}:{height:u,width:0}),g[f[0]]=h?n[0]:u,v[f[1]]=h?n[1]:0,s.animate(g,m,t.easing).animate(v,m,t.easing,function(){l&&a.hide(),e.effects.restore(a,o),e.effects.removeWrapper(a),i()})},e.effects.effect.highlight=function(t,i){var s=e(this),n=[\"backgroundImage\",\"backgroundColor\",\"opacity\"],a=e.effects.setMode(s,t.mode||\"show\"),o={backgroundColor:s.css(\"backgroundColor\")};\"hide\"===a&&(o.opacity=0),e.effects.save(s,n),s.show().css({backgroundImage:\"none\",backgroundColor:t.color||\"#ffff99\"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){\"hide\"===a&&s.hide(),e.effects.restore(s,n),i()}})},e.effects.effect.size=function(t,i){var s,n,a,o=e(this),r=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"width\",\"height\",\"overflow\",\"opacity\"],h=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"overflow\",\"opacity\"],l=[\"width\",\"height\",\"overflow\"],u=[\"fontSize\"],d=[\"borderTopWidth\",\"borderBottomWidth\",\"paddingTop\",\"paddingBottom\"],c=[\"borderLeftWidth\",\"borderRightWidth\",\"paddingLeft\",\"paddingRight\"],p=e.effects.setMode(o,t.mode||\"effect\"),f=t.restore||\"effect\"!==p,m=t.scale||\"both\",g=t.origin||[\"middle\",\"center\"],v=o.css(\"position\"),y=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};\"show\"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},\"toggle\"===t.mode&&\"show\"===p?(o.from=t.to||b,o.to=t.from||s):(o.from=t.from||(\"show\"===p?b:s),o.to=t.to||(\"hide\"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},(\"box\"===m||\"both\"===m)&&(a.from.y!==a.to.y&&(y=y.concat(d),o.from=e.effects.setTransition(o,d,a.from.y,o.from),o.to=e.effects.setTransition(o,d,a.to.y,o.to)),a.from.x!==a.to.x&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,a.from.x,o.from),o.to=e.effects.setTransition(o,c,a.to.x,o.to))),(\"content\"===m||\"both\"===m)&&a.from.y!==a.to.y&&(y=y.concat(u).concat(l),o.from=e.effects.setTransition(o,u,a.from.y,o.from),o.to=e.effects.setTransition(o,u,a.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css(\"overflow\",\"hidden\").css(o.from),g&&(n=e.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),(\"content\"===m||\"both\"===m)&&(d=d.concat([\"marginTop\",\"marginBottom\"]).concat(u),c=c.concat([\"marginLeft\",\"marginRight\"]),l=r.concat(d).concat(c),o.find(\"*[width]\").each(function(){var i=e(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};\nf&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i.css(i.from),i.animate(i.to,t.duration,t.easing,function(){f&&e.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===o.to.opacity&&o.css(\"opacity\",o.from.opacity),\"hide\"===p&&o.hide(),e.effects.restore(o,y),f||(\"static\"===v?o.css({position:\"relative\",top:o.to.top,left:o.to.left}):e.each([\"top\",\"left\"],function(e,t){o.css(t,function(t,i){var s=parseInt(i,10),n=e?o.to.left:o.to.top;return\"auto\"===i?n+\"px\":s+n+\"px\"})})),e.effects.removeWrapper(o),i()}})},e.effects.effect.scale=function(t,i){var s=e(this),n=e.extend(!0,{},t),a=e.effects.setMode(s,t.mode||\"effect\"),o=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:\"hide\"===a?0:100),r=t.direction||\"both\",h=t.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},u={y:\"horizontal\"!==r?o/100:1,x:\"vertical\"!==r?o/100:1};n.effect=\"size\",n.queue=!1,n.complete=i,\"effect\"!==a&&(n.origin=h||[\"middle\",\"center\"],n.restore=!0),n.from=t.from||(\"show\"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*u.y,width:l.width*u.x,outerHeight:l.outerHeight*u.y,outerWidth:l.outerWidth*u.x},n.fade&&(\"show\"===a&&(n.from.opacity=0,n.to.opacity=1),\"hide\"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},e.effects.effect.puff=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||\"hide\"),a=\"hide\"===n,o=parseInt(t.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};e.extend(t,{effect:\"scale\",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(t)},e.effects.effect.pulsate=function(t,i){var s,n=e(this),a=e.effects.setMode(n,t.mode||\"show\"),o=\"show\"===a,r=\"hide\"===a,h=o||\"hide\"===a,l=2*(t.times||5)+(h?1:0),u=t.duration/l,d=0,c=n.queue(),p=c.length;for((o||!n.is(\":visible\"))&&(n.css(\"opacity\",0).show(),d=1),s=1;l>s;s++)n.animate({opacity:d},u,t.easing),d=1-d;n.animate({opacity:d},u,t.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&c.splice.apply(c,[1,0].concat(c.splice(p,l+1))),n.dequeue()},e.effects.effect.shake=function(t,i){var s,n=e(this),a=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"height\",\"width\"],o=e.effects.setMode(n,t.mode||\"effect\"),r=t.direction||\"left\",h=t.distance||20,l=t.times||3,u=2*l+1,d=Math.round(t.duration/u),c=\"up\"===r||\"down\"===r?\"top\":\"left\",p=\"up\"===r||\"left\"===r,f={},m={},g={},v=n.queue(),y=v.length;for(e.effects.save(n,a),n.show(),e.effects.createWrapper(n),f[c]=(p?\"-=\":\"+=\")+h,m[c]=(p?\"+=\":\"-=\")+2*h,g[c]=(p?\"-=\":\"+=\")+2*h,n.animate(f,d,t.easing),s=1;l>s;s++)n.animate(m,d,t.easing).animate(g,d,t.easing);n.animate(m,d,t.easing).animate(f,d/2,t.easing).queue(function(){\"hide\"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}),y>1&&v.splice.apply(v,[1,0].concat(v.splice(y,u+1))),n.dequeue()},e.effects.effect.slide=function(t,i){var s,n=e(this),a=[\"position\",\"top\",\"bottom\",\"left\",\"right\",\"width\",\"height\"],o=e.effects.setMode(n,t.mode||\"show\"),r=\"show\"===o,h=t.direction||\"left\",l=\"up\"===h||\"down\"===h?\"top\":\"left\",u=\"up\"===h||\"left\"===h,d={};e.effects.save(n,a),n.show(),s=t.distance||n[\"top\"===l?\"outerHeight\":\"outerWidth\"](!0),e.effects.createWrapper(n).css({overflow:\"hidden\"}),r&&n.css(l,u?isNaN(s)?\"-\"+s:-s:s),d[l]=(r?u?\"+=\":\"-=\":u?\"-=\":\"+=\")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){\"hide\"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.transfer=function(t,i){var s=e(this),n=e(t.to),a=\"fixed\"===n.css(\"position\"),o=e(\"body\"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),u={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),c=e(\"<div class='ui-effects-transfer'></div>\").appendTo(document.body).addClass(t.className).css({top:d.top-r,left:d.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?\"fixed\":\"absolute\"}).animate(u,t.duration,t.easing,function(){c.remove(),i()})},e.widget(\"ui.progressbar\",{version:\"1.11.4\",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass(\"ui-progressbar ui-widget ui-widget-content ui-corner-all\").attr({role:\"progressbar\",\"aria-valuemin\":this.min}),this.valueDiv=e(\"<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>\").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass(\"ui-progressbar ui-widget ui-widget-content ui-corner-all\").removeAttr(\"role\").removeAttr(\"aria-valuemin\").removeAttr(\"aria-valuemax\").removeAttr(\"aria-valuenow\"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,\"number\"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){\"max\"===e&&(t=Math.max(this.min,t)),\"disabled\"===e&&this.element.toggleClass(\"ui-state-disabled\",!!t).attr(\"aria-disabled\",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass(\"ui-corner-right\",t===this.options.max).width(i.toFixed(0)+\"%\"),this.element.toggleClass(\"ui-progressbar-indeterminate\",this.indeterminate),this.indeterminate?(this.element.removeAttr(\"aria-valuenow\"),this.overlayDiv||(this.overlayDiv=e(\"<div class='ui-progressbar-overlay'></div>\").appendTo(this.valueDiv))):(this.element.attr({\"aria-valuemax\":this.options.max,\"aria-valuenow\":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger(\"change\")),t===this.options.max&&this._trigger(\"complete\")}}),e.widget(\"ui.selectable\",e.ui.mouse,{version:\"1.11.4\",options:{appendTo:\"body\",autoRefresh:!0,distance:0,filter:\"*\",tolerance:\"touch\",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass(\"ui-selectable\"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass(\"ui-selectee\"),t.each(function(){var t=e(this),i=t.offset();e.data(this,\"selectable-item\",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass(\"ui-selected\"),selecting:t.hasClass(\"ui-selecting\"),unselecting:t.hasClass(\"ui-unselecting\")})})},this.refresh(),this.selectees=t.addClass(\"ui-selectee\"),this._mouseInit(),this.helper=e(\"<div class='ui-selectable-helper'></div>\")},_destroy:function(){this.selectees.removeClass(\"ui-selectee\").removeData(\"selectable-item\"),this.element.removeClass(\"ui-selectable ui-selectable-disabled\"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger(\"start\",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(\".ui-selected\").each(function(){var s=e.data(this,\"selectable-item\");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass(\"ui-selected\"),s.selected=!1,s.$element.addClass(\"ui-unselecting\"),s.unselecting=!0,i._trigger(\"unselecting\",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,\"selectable-item\");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass(\"ui-selected\"),n.$element.removeClass(s?\"ui-unselecting\":\"ui-selected\").addClass(s?\"ui-selecting\":\"ui-unselecting\"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger(\"selecting\",t,{selecting:n.element}):i._trigger(\"unselecting\",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,\"selectable-item\"),l=!1;i&&i.element!==s.element[0]&&(\"touch\"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):\"fit\"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass(\"ui-selected\"),i.selected=!1),i.unselecting&&(i.$element.removeClass(\"ui-unselecting\"),i.unselecting=!1),i.selecting||(i.$element.addClass(\"ui-selecting\"),i.selecting=!0,s._trigger(\"selecting\",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass(\"ui-selecting\"),i.selecting=!1,i.$element.addClass(\"ui-selected\"),i.selected=!0):(i.$element.removeClass(\"ui-selecting\"),i.selecting=!1,i.startselected&&(i.$element.addClass(\"ui-unselecting\"),i.unselecting=!0),s._trigger(\"unselecting\",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass(\"ui-selected\"),i.selected=!1,i.$element.addClass(\"ui-unselecting\"),i.unselecting=!0,s._trigger(\"unselecting\",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(\".ui-unselecting\",this.element[0]).each(function(){var s=e.data(this,\"selectable-item\");s.$element.removeClass(\"ui-unselecting\"),s.unselecting=!1,s.startselected=!1,i._trigger(\"unselected\",t,{unselected:s.element})}),e(\".ui-selecting\",this.element[0]).each(function(){var s=e.data(this,\"selectable-item\");s.$element.removeClass(\"ui-selecting\").addClass(\"ui-selected\"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger(\"selected\",t,{selected:s.element})}),this._trigger(\"stop\",t),this.helper.remove(),!1}}),e.widget(\"ui.selectmenu\",{version:\"1.11.4\",defaultElement:\"<select>\",options:{appendTo:null,disabled:null,icons:{button:\"ui-icon-triangle-1-s\"},position:{my:\"left top\",at:\"left bottom\",collision:\"none\"},width:null,change:null,close:null,focus:null,open:null,select:null},_create:function(){var e=this.element.uniqueId().attr(\"id\");this.ids={element:e,button:e+\"-button\",menu:e+\"-menu\"},this._drawButton(),this._drawMenu(),this.options.disabled&&this.disable()},_drawButton:function(){var t=this;this.label=e(\"label[for='\"+this.ids.element+\"']\").attr(\"for\",this.ids.button),this._on(this.label,{click:function(e){this.button.focus(),e.preventDefault()}}),this.element.hide(),this.button=e(\"<span>\",{\"class\":\"ui-selectmenu-button ui-widget ui-state-default ui-corner-all\",tabindex:this.options.disabled?-1:0,id:this.ids.button,role:\"combobox\",\"aria-expanded\":\"false\",\"aria-autocomplete\":\"list\",\"aria-owns\":this.ids.menu,\"aria-haspopup\":\"true\"}).insertAfter(this.element),e(\"<span>\",{\"class\":\"ui-icon \"+this.options.icons.button}).prependTo(this.button),this.buttonText=e(\"<span>\",{\"class\":\"ui-selectmenu-text\"}).appendTo(this.button),this._setText(this.buttonText,this.element.find(\"option:selected\").text()),this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one(\"focusin\",function(){t.menuItems||t._refreshMenu()}),this._hoverable(this.button),this._focusable(this.button)},_drawMenu:function(){var t=this;this.menu=e(\"<ul>\",{\"aria-hidden\":\"true\",\"aria-labelledby\":this.ids.button,id:this.ids.menu}),this.menuWrap=e(\"<div>\",{\"class\":\"ui-selectmenu-menu ui-front\"}).append(this.menu).appendTo(this._appendTo()),this.menuInstance=this.menu.menu({role:\"listbox\",select:function(e,i){e.preventDefault(),t._setSelection(),t._select(i.item.data(\"ui-selectmenu-item\"),e)},focus:function(e,i){var s=i.item.data(\"ui-selectmenu-item\");null!=t.focusIndex&&s.index!==t.focusIndex&&(t._trigger(\"focus\",e,{item:s}),t.isOpen||t._select(s,e)),t.focusIndex=s.index,t.button.attr(\"aria-activedescendant\",t.menuItems.eq(s.index).attr(\"id\"))}}).menu(\"instance\"),this.menu.addClass(\"ui-corner-bottom\").removeClass(\"ui-corner-all\"),this.menuInstance._off(this.menu,\"mouseleave\"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this._setText(this.buttonText,this._getSelectedItem().text()),this.options.width||this._resizeButton()},_refreshMenu:function(){this.menu.empty();var e,t=this.element.find(\"option\");t.length&&(this._parseOptions(t),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find(\"li\").not(\".ui-selectmenu-optgroup\"),e=this._getSelectedItem(),this.menuInstance.focus(null,e),this._setAria(e.data(\"ui-selectmenu-item\")),this._setOption(\"disabled\",this.element.prop(\"disabled\")))},open:function(e){this.options.disabled||(this.menuItems?(this.menu.find(\".ui-state-focus\").removeClass(\"ui-state-focus\"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger(\"open\",e))},_position:function(){this.menuWrap.position(e.extend({of:this.button},this.options.position))},close:function(e){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this.range=null,this._off(this.document),this._trigger(\"close\",e))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderMenu:function(t,i){var s=this,n=\"\";e.each(i,function(i,a){a.optgroup!==n&&(e(\"<li>\",{\"class\":\"ui-selectmenu-optgroup ui-menu-divider\"+(a.element.parent(\"optgroup\").prop(\"disabled\")?\" ui-state-disabled\":\"\"),text:a.optgroup}).appendTo(t),n=a.optgroup),s._renderItemData(t,a)})},_renderItemData:function(e,t){return this._renderItem(e,t).data(\"ui-selectmenu-item\",t)},_renderItem:function(t,i){var s=e(\"<li>\");return i.disabled&&s.addClass(\"ui-state-disabled\"),this._setText(s,i.label),s.appendTo(t)},_setText:function(e,t){t?e.text(t):e.html(\"&#160;\")},_move:function(e,t){var i,s,n=\".ui-menu-item\";this.isOpen?i=this.menuItems.eq(this.focusIndex):(i=this.menuItems.eq(this.element[0].selectedIndex),n+=\":not(.ui-state-disabled)\"),s=\"first\"===e||\"last\"===e?i[\"first\"===e?\"prevAll\":\"nextAll\"](n).eq(-1):i[e+\"All\"](n).eq(0),s.length&&this.menuInstance.focus(t,s)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex)},_toggle:function(e){this[this.isOpen?\"close\":\"open\"](e)},_setSelection:function(){var e;this.range&&(window.getSelection?(e=window.getSelection(),e.removeAllRanges(),e.addRange(this.range)):this.range.select(),this.button.focus())},_documentClick:{mousedown:function(t){this.isOpen&&(e(t.target).closest(\".ui-selectmenu-menu, #\"+this.ids.button).length||this.close(t))}},_buttonEvents:{mousedown:function(){var e;window.getSelection?(e=window.getSelection(),e.rangeCount&&(this.range=e.getRangeAt(0))):this.range=document.selection.createRange()},click:function(e){this._setSelection(),this._toggle(e)},keydown:function(t){var i=!0;switch(t.keyCode){case e.ui.keyCode.TAB:case e.ui.keyCode.ESCAPE:this.close(t),i=!1;break;case e.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(t);break;case e.ui.keyCode.UP:t.altKey?this._toggle(t):this._move(\"prev\",t);break;case e.ui.keyCode.DOWN:t.altKey?this._toggle(t):this._move(\"next\",t);break;case e.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(t):this._toggle(t);break;case e.ui.keyCode.LEFT:this._move(\"prev\",t);break;case e.ui.keyCode.RIGHT:this._move(\"next\",t);break;case e.ui.keyCode.HOME:case e.ui.keyCode.PAGE_UP:this._move(\"first\",t);break;case e.ui.keyCode.END:case e.ui.keyCode.PAGE_DOWN:this._move(\"last\",t);break;default:this.menu.trigger(t),i=!1}i&&t.preventDefault()}},_selectFocusedItem:function(e){var t=this.menuItems.eq(this.focusIndex);t.hasClass(\"ui-state-disabled\")||this._select(t.data(\"ui-selectmenu-item\"),e)},_select:function(e,t){var i=this.element[0].selectedIndex;this.element[0].selectedIndex=e.index,this._setText(this.buttonText,e.label),this._setAria(e),this._trigger(\"select\",t,{item:e}),e.index!==i&&this._trigger(\"change\",t,{item:e}),this.close(t)},_setAria:function(e){var t=this.menuItems.eq(e.index).attr(\"id\");this.button.attr({\"aria-labelledby\":t,\"aria-activedescendant\":t}),this.menu.attr(\"aria-activedescendant\",t)},_setOption:function(e,t){\"icons\"===e&&this.button.find(\"span.ui-icon\").removeClass(this.options.icons.button).addClass(t.button),this._super(e,t),\"appendTo\"===e&&this.menuWrap.appendTo(this._appendTo()),\"disabled\"===e&&(this.menuInstance.option(\"disabled\",t),this.button.toggleClass(\"ui-state-disabled\",t).attr(\"aria-disabled\",t),this.element.prop(\"disabled\",t),t?(this.button.attr(\"tabindex\",-1),this.close()):this.button.attr(\"tabindex\",0)),\"width\"===e&&this._resizeButton()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(\".ui-front\")),t.length||(t=this.document[0].body),t},_toggleAttr:function(){this.button.toggleClass(\"ui-corner-top\",this.isOpen).toggleClass(\"ui-corner-all\",!this.isOpen).attr(\"aria-expanded\",this.isOpen),this.menuWrap.toggleClass(\"ui-selectmenu-open\",this.isOpen),this.menu.attr(\"aria-hidden\",!this.isOpen)},_resizeButton:function(){var e=this.options.width;e||(e=this.element.show().outerWidth(),this.element.hide()),this.button.outerWidth(e)},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width(\"\").outerWidth()+1))},_getCreateOptions:function(){return{disabled:this.element.prop(\"disabled\")}},_parseOptions:function(t){var i=[];t.each(function(t,s){var n=e(s),a=n.parent(\"optgroup\");i.push({element:n,index:t,value:n.val(),label:n.text(),optgroup:a.attr(\"label\")||\"\",disabled:a.prop(\"disabled\")||n.prop(\"disabled\")})}),this.items=i},_destroy:function(){this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.label.attr(\"for\",this.ids.element)}}),e.widget(\"ui.slider\",e.ui.mouse,{version:\"1.11.4\",widgetEventPrefix:\"slide\",options:{animate:!1,distance:0,max:100,min:0,orientation:\"horizontal\",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this.element.addClass(\"ui-slider ui-slider-\"+this.orientation+\" ui-widget\"+\" ui-widget-content\"+\" ui-corner-all\"),this._refresh(),this._setOption(\"disabled\",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,i,s=this.options,n=this.element.find(\".ui-slider-handle\").addClass(\"ui-state-default ui-corner-all\"),a=\"<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>\",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),t=n.length;i>t;t++)o.push(a);this.handles=n.add(e(o.join(\"\")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(t){e(this).data(\"ui-slider-handle-index\",t)})},_createRange:function(){var t=this.options,i=\"\";t.range?(t.range===!0&&(t.values?t.values.length&&2!==t.values.length?t.values=[t.values[0],t.values[0]]:e.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass(\"ui-slider-range-min ui-slider-range-max\").css({left:\"\",bottom:\"\"}):(this.range=e(\"<div></div>\").appendTo(this.element),i=\"ui-slider-range ui-widget-header ui-corner-all\"),this.range.addClass(i+(\"min\"===t.range||\"max\"===t.range?\" ui-slider-range-\"+t.range:\"\"))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass(\"ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all\"),this._mouseDestroy()},_mouseCapture:function(t){var i,s,n,a,o,r,h,l,u=this,d=this.options;return d.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:t.pageX,y:t.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var i=Math.abs(s-u.values(t));(n>i||n===i&&(t===u._lastChangedValue||u.values(t)===d.min))&&(n=i,a=e(this),o=t)}),r=this._start(t,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass(\"ui-state-active\").focus(),h=a.offset(),l=!e(t.target).parents().addBack().is(\".ui-slider-handle\"),this._clickOffset=l?{left:0,top:0}:{left:t.pageX-h.left-a.width()/2,top:t.pageY-h.top-a.height()/2-(parseInt(a.css(\"borderTopWidth\"),10)||0)-(parseInt(a.css(\"borderBottomWidth\"),10)||0)+(parseInt(a.css(\"marginTop\"),10)||0)},this.handles.hasClass(\"ui-state-hover\")||this._slide(t,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},i=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,i),!1},_mouseStop:function(e){return this.handles.removeClass(\"ui-state-active\"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=\"vertical\"===this.options.orientation?\"vertical\":\"horizontal\"},_normValueFromMouse:function(e){var t,i,s,n,a;return\"horizontal\"===this.orientation?(t=this.elementSize.width,i=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,i=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/t,s>1&&(s=1),0>s&&(s=0),\"vertical\"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(e,t){var i={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._trigger(\"start\",e,i)},_slide:function(e,t,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(t?0:1),2===this.options.values.length&&this.options.range===!0&&(0===t&&i>s||1===t&&s>i)&&(i=s),i!==this.values(t)&&(n=this.values(),n[t]=i,a=this._trigger(\"slide\",e,{handle:this.handles[t],value:i,values:n}),s=this.values(t?0:1),a!==!1&&this.values(t,i))):i!==this.value()&&(a=this._trigger(\"slide\",e,{handle:this.handles[t],value:i}),a!==!1&&this.value(i))},_stop:function(e,t){var i={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._trigger(\"stop\",e,i)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._lastChangedValue=t,this._trigger(\"change\",e,i)}},value:function(e){return arguments.length?(this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(t,i){var s,n,a;if(arguments.length>1)return this.options.values[t]=this._trimAlignValue(i),this._refreshValue(),this._change(null,t),void 0;if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(t,i){var s,n=0;switch(\"range\"===t&&this.options.range===!0&&(\"min\"===i?(this.options.value=this._values(0),this.options.values=null):\"max\"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),e.isArray(this.options.values)&&(n=this.options.values.length),\"disabled\"===t&&this.element.toggleClass(\"ui-state-disabled\",!!i),this._super(t,i),t){case\"orientation\":this._detectOrientation(),this.element.removeClass(\"ui-slider-horizontal ui-slider-vertical\").addClass(\"ui-slider-\"+this.orientation),this._refreshValue(),this.handles.css(\"horizontal\"===i?\"bottom\":\"left\",\"\");break;case\"value\":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case\"values\":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case\"step\":case\"min\":case\"max\":this._animateOff=!0,this._calculateNewMax(),this._refreshValue(),this._animateOff=!1;break;case\"range\":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e)},_values:function(e){var t,i,s;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(e){if(this._valueMin()>=e)return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,i=(e-this._valueMin())%t,s=e-i;return 2*Math.abs(i)>=t&&(s+=i>0?t:-t),parseFloat(s.toFixed(5))},_calculateNewMax:function(){var e=this.options.max,t=this._valueMin(),i=this.options.step,s=Math.floor(+(e-t).toFixed(this._precision())/i)*i;e=s+t,this.max=parseFloat(e.toFixed(this._precision()))},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=\"\"+e,i=t.indexOf(\".\");return-1===i?0:t.length-i-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshValue:function(){var t,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u[\"horizontal\"===h.orientation?\"left\":\"bottom\"]=i+\"%\",e(this).stop(1,1)[l?\"animate\":\"css\"](u,r.animate),h.options.range===!0&&(\"horizontal\"===h.orientation?(0===s&&h.range.stop(1,1)[l?\"animate\":\"css\"]({left:i+\"%\"},r.animate),1===s&&h.range[l?\"animate\":\"css\"]({width:i-t+\"%\"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?\"animate\":\"css\"]({bottom:i+\"%\"},r.animate),1===s&&h.range[l?\"animate\":\"css\"]({height:i-t+\"%\"},{queue:!1,duration:r.animate}))),t=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u[\"horizontal\"===this.orientation?\"left\":\"bottom\"]=i+\"%\",this.handle.stop(1,1)[l?\"animate\":\"css\"](u,r.animate),\"min\"===o&&\"horizontal\"===this.orientation&&this.range.stop(1,1)[l?\"animate\":\"css\"]({width:i+\"%\"},r.animate),\"max\"===o&&\"horizontal\"===this.orientation&&this.range[l?\"animate\":\"css\"]({width:100-i+\"%\"},{queue:!1,duration:r.animate}),\"min\"===o&&\"vertical\"===this.orientation&&this.range.stop(1,1)[l?\"animate\":\"css\"]({height:i+\"%\"},r.animate),\"max\"===o&&\"vertical\"===this.orientation&&this.range[l?\"animate\":\"css\"]({height:100-i+\"%\"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(t){var i,s,n,a,o=e(t.target).data(\"ui-slider-handle-index\");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(t.preventDefault(),!this._keySliding&&(this._keySliding=!0,e(t.target).addClass(\"ui-state-active\"),i=this._start(t,o),i===!1))return}switch(a=this.options.step,s=n=this.options.values&&this.options.values.length?this.values(o):this.value(),t.keyCode){case e.ui.keyCode.HOME:n=this._valueMin();break;case e.ui.keyCode.END:n=this._valueMax();break;case e.ui.keyCode.PAGE_UP:n=this._trimAlignValue(s+(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.PAGE_DOWN:n=this._trimAlignValue(s-(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(s===this._valueMax())return;n=this._trimAlignValue(s+a);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(s===this._valueMin())return;n=this._trimAlignValue(s-a)}this._slide(t,o,n)},keyup:function(t){var i=e(t.target).data(\"ui-slider-handle-index\");this._keySliding&&(this._keySliding=!1,this._stop(t,i),this._change(t,i),e(t.target).removeClass(\"ui-state-active\"))}}}),e.widget(\"ui.sortable\",e.ui.mouse,{version:\"1.11.4\",widgetEventPrefix:\"sort\",ready:!1,options:{appendTo:\"parent\",axis:!1,connectWith:!1,containment:!1,cursor:\"auto\",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:\"original\",items:\"> *\",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:\"default\",tolerance:\"intersect\",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(e,t,i){return e>=t&&t+i>e},_isFloating:function(e){return/left|right/.test(e.css(\"float\"))||/inline|table-cell/.test(e.css(\"display\"))},_create:function(){this.containerCache={},this.element.addClass(\"ui-sortable\"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(e,t){this._super(e,t),\"handle\"===e&&this._setHandleClassName()},_setHandleClassName:function(){this.element.find(\".ui-sortable-handle\").removeClass(\"ui-sortable-handle\"),e.each(this.items,function(){(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item).addClass(\"ui-sortable-handle\")})},_destroy:function(){this.element.removeClass(\"ui-sortable ui-sortable-disabled\").find(\".ui-sortable-handle\").removeClass(\"ui-sortable-handle\"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+\"-item\");return this},_mouseCapture:function(t,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||\"static\"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,a.widgetName+\"-item\")===a?(s=e(this),!1):void 0}),e.data(t.target,a.widgetName+\"-item\")===a&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find(\"*\").addBack().each(function(){this===t.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css(\"position\",\"absolute\"),this.cssPosition=this.helper.css(\"position\"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&\"auto\"!==o.cursor&&(a=this.document.find(\"body\"),this.storedCursor=a.css(\"cursor\"),a.css(\"cursor\",o.cursor),this.storedStylesheet=e(\"<style>*{ cursor: \"+o.cursor+\" !important; }</style>\").appendTo(a)),o.opacity&&(this.helper.css(\"opacity\")&&(this._storedOpacity=this.helper.css(\"opacity\")),this.helper.css(\"opacity\",o.opacity)),o.zIndex&&(this.helper.css(\"zIndex\")&&(this._storedZIndex=this.helper.css(\"zIndex\")),this.helper.css(\"zIndex\",o.zIndex)),this.scrollParent[0]!==this.document[0]&&\"HTML\"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger(\"start\",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger(\"activate\",t,this._uiHash(this));\nreturn e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass(\"ui-sortable-helper\"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo(\"absolute\"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&\"HTML\"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+o.scrollSpeed:t.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+o.scrollSpeed:t.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(t.pageY-this.document.scrollTop()<o.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-o.scrollSpeed):this.window.height()-(t.pageY-this.document.scrollTop())<o.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+o.scrollSpeed)),t.pageX-this.document.scrollLeft()<o.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-o.scrollSpeed):this.window.width()-(t.pageX-this.document.scrollLeft())<o.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+o.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)),this.positionAbs=this._convertPositionTo(\"absolute\"),this.options.axis&&\"y\"===this.options.axis||(this.helper[0].style.left=this.position.left+\"px\"),this.options.axis&&\"x\"===this.options.axis||(this.helper[0].style.top=this.position.top+\"px\"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?\"next\":\"prev\"]()[0]!==n&&!e.contains(this.placeholder[0],n)&&(\"semi-dynamic\"===this.options.type?!e.contains(this.element[0],n):!0)){if(this.direction=1===a?\"down\":\"up\",\"pointer\"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger(\"change\",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger(\"sort\",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&\"x\"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),a&&\"y\"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),\"original\"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger(\"deactivate\",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger(\"out\",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),\"original\"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||\"id\")||\"\").match(t.expression||/(.+)[\\-=_](.+)/);i&&s.push((t.key||i[1]+\"[]\")+\"=\"+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+\"=\"),s.join(\"&\")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||\"id\")||\"\")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=e.left,o=a+e.width,r=e.top,h=r+e.height,l=this.offset.click.top,u=this.offset.click.left,d=\"x\"===this.options.axis||s+l>r&&h>s+l,c=\"y\"===this.options.axis||t+u>a&&o>t+u,p=d&&c;return\"pointer\"===this.options.tolerance||this.options.forcePointerForContainers||\"pointer\"!==this.options.tolerance&&this.helperProportions[this.floating?\"width\":\"height\"]>e[this.floating?\"width\":\"height\"]?p:t+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(e){var t=\"x\"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top,e.height),i=\"y\"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left,e.width),s=t&&i,n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return s?this.floating?a&&\"right\"===a||\"down\"===n?2:1:n&&(\"down\"===n?2:1):!1},_intersectsWithSides:function(e){var t=this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?\"right\"===n&&i||\"left\"===n&&!i:s&&(\"down\"===s&&t||\"up\"===s&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?\"down\":\"up\")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?\"right\":\"left\")},refresh:function(e){return this._refreshItems(e),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){function i(){r.push(this)}var s,n,a,o,r=[],h=[],l=this._connectWith();if(l&&t)for(s=l.length-1;s>=0;s--)for(a=e(l[s],this.document[0]),n=a.length-1;n>=0;n--)o=e.data(a[n],this.widgetFullName),o&&o!==this&&!o.options.disabled&&h.push([e.isFunction(o.options.items)?o.options.items.call(o.element):e(o.options.items,o.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"),o]);for(h.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(\".ui-sortable-helper\").not(\".ui-sortable-placeholder\"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(\":data(\"+this.widgetName+\"-item)\");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,u=this.items,d=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],c=this._connectWith();if(c&&this.ready)for(i=c.length-1;i>=0;i--)for(n=e(c[i],this.document[0]),s=n.length-1;s>=0;s--)a=e.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(d.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a));for(i=d.length-1;i>=0;i--)for(o=d[i][1],r=d[i][0],s=0,l=r.length;l>s;s++)h=e(r[s]),h.data(this.widgetName+\"-item\",o),u.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.floating=this.items.length?\"x\"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),n=e(\"<\"+s+\">\",t.document[0]).addClass(i||t.currentItem[0].className+\" ui-sortable-placeholder\").removeClass(\"ui-sortable-helper\");return\"tbody\"===s?t._createTrPlaceholder(t.currentItem.find(\"tr\").eq(0),e(\"<tr>\",t.document[0]).appendTo(n)):\"tr\"===s?t._createTrPlaceholder(t.currentItem,n):\"img\"===s&&n.attr(\"src\",t.currentItem.attr(\"src\")),i||n.css(\"visibility\",\"hidden\"),n},update:function(e,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css(\"paddingTop\")||0,10)-parseInt(t.currentItem.css(\"paddingBottom\")||0,10)),n.width()||n.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css(\"paddingLeft\")||0,10)-parseInt(t.currentItem.css(\"paddingRight\")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_createTrPlaceholder:function(t,i){var s=this;t.children().each(function(){e(\"<td>&#160;</td>\",s.document[0]).attr(\"colspan\",e(this).attr(\"colspan\")||1).appendTo(i)})},_contactContainers:function(t){var i,s,n,a,o,r,h,l,u,d,c=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!e.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(c&&e.contains(this.containers[i].element[0],c.element[0]))continue;c=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger(\"out\",t,this._uiHash(this)),this.containers[i].containerCache.over=0);if(c)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger(\"over\",t,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,a=null,u=c.floating||this._isFloating(this.currentItem),o=u?\"left\":\"top\",r=u?\"width\":\"height\",d=u?\"clientX\":\"clientY\",s=this.items.length-1;s>=0;s--)e.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[o],l=!1,t[d]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(t[d]-h)&&(n=Math.abs(t[d]-h),a=this.items[s],this.direction=l?\"up\":\"down\"));if(!a&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger(\"over\",t,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;a?this._rearrange(t,a,null,!0):this._rearrange(t,null,this.containers[p].element,!0),this._trigger(\"change\",t,this._uiHash()),this.containers[p]._trigger(\"change\",t,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger(\"over\",t,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):\"clone\"===i.helper?this.currentItem.clone():this.currentItem;return s.parents(\"body\").length||e(\"parent\"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css(\"position\"),top:this.currentItem.css(\"top\"),left:this.currentItem.css(\"left\")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){\"string\"==typeof t&&(t=t.split(\" \")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),\"left\"in t&&(this.offset.click.left=t.left+this.margins.left),\"right\"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),\"top\"in t&&(this.offset.click.top=t.top+this.margins.top),\"bottom\"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return\"absolute\"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&\"html\"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css(\"borderTopWidth\"),10)||0),left:t.left+(parseInt(this.offsetParent.css(\"borderLeftWidth\"),10)||0)}},_getRelativeOffset:function(){if(\"relative\"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css(\"top\"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css(\"left\"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css(\"marginLeft\"),10)||0,top:parseInt(this.currentItem.css(\"marginTop\"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;\"parent\"===n.containment&&(n.containment=this.helper[0].parentNode),(\"document\"===n.containment||\"window\"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,\"document\"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,(\"document\"===n.containment?this.document.width():this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(t=e(n.containment)[0],i=e(n.containment).offset(),s=\"hidden\"!==e(t).css(\"overflow\"),this.containment=[i.left+(parseInt(e(t).css(\"borderLeftWidth\"),10)||0)+(parseInt(e(t).css(\"paddingLeft\"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css(\"borderTopWidth\"),10)||0)+(parseInt(e(t).css(\"paddingTop\"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css(\"borderLeftWidth\"),10)||0)-(parseInt(e(t).css(\"paddingRight\"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css(\"borderTopWidth\"),10)||0)-(parseInt(e(t).css(\"paddingBottom\"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s=\"absolute\"===t?1:-1,n=\"absolute\"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-(\"fixed\"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-(\"fixed\"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(t){var i,s,n=this.options,a=t.pageX,o=t.pageY,r=\"absolute\"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return\"relative\"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(a=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(a=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(\"fixed\"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(\"fixed\"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],\"down\"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){function i(e,t,i){return function(s){i._trigger(e,s,t._uiHash(t))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)(\"auto\"===this._storedCSS[s]||\"static\"===this._storedCSS[s])&&(this._storedCSS[s]=\"\");this.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\")}else this.currentItem.show();for(this.fromOutside&&!t&&n.push(function(e){this._trigger(\"receive\",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(\".ui-sortable-helper\")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||n.push(function(e){this._trigger(\"update\",e,this._uiHash())}),this!==this.currentContainer&&(t||(n.push(function(e){this._trigger(\"remove\",e,this._uiHash())}),n.push(function(e){return function(t){e._trigger(\"receive\",t,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(e){return function(t){e._trigger(\"update\",t,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)t||n.push(i(\"deactivate\",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i(\"out\",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find(\"body\").css(\"cursor\",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css(\"opacity\",this._storedOpacity),this._storedZIndex&&this.helper.css(\"zIndex\",\"auto\"===this._storedZIndex?\"\":this._storedZIndex),this.dragging=!1,t||this._trigger(\"beforeStop\",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!t){for(s=0;n.length>s;s++)n[s].call(this,e);this._trigger(\"stop\",e,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}}),e.widget(\"ui.spinner\",{version:\"1.11.4\",defaultElement:\"<input>\",widgetEventPrefix:\"spin\",options:{culture:null,icons:{down:\"ui-icon-triangle-1-s\",up:\"ui-icon-triangle-1-n\"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption(\"max\",this.options.max),this._setOption(\"min\",this.options.min),this._setOption(\"step\",this.options.step),\"\"!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr(\"autocomplete\")}})},_getCreateOptions:function(){var t={},i=this.element;return e.each([\"min\",\"max\",\"step\"],function(e,s){var n=i.attr(s);void 0!==n&&n.length&&(t[s]=n)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:\"_stop\",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger(\"change\",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},\"mousedown .ui-spinner-button\":function(t){function i(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass(\"ui-spinner-up\")?1:-1,t)},\"mouseup .ui-spinner-button\":\"_stop\",\"mouseenter .ui-spinner-button\":function(t){return e(t.currentTarget).hasClass(\"ui-state-active\")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass(\"ui-spinner-up\")?1:-1,t),void 0):void 0},\"mouseleave .ui-spinner-button\":\"_stop\"},_draw:function(){var e=this.uiSpinner=this.element.addClass(\"ui-spinner-input\").attr(\"autocomplete\",\"off\").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr(\"role\",\"spinbutton\"),this.buttons=e.find(\".ui-spinner-button\").attr(\"tabIndex\",-1).button().removeClass(\"ui-corner-all\"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var i=this.options,s=e.ui.keyCode;switch(t.keyCode){case s.UP:return this._repeat(null,1,t),!0;case s.DOWN:return this._repeat(null,-1,t),!0;case s.PAGE_UP:return this._repeat(null,i.page,t),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,t),!0}return!1},_uiSpinnerHtml:function(){return\"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>\"},_buttonHtml:function(){return\"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon \"+this.options.icons.up+\"'>&#9650;</span>\"+\"</a>\"+\"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>\"+\"<span class='ui-icon \"+this.options.icons.down+\"'>&#9660;</span>\"+\"</a>\"},_start:function(e){return this.spinning||this._trigger(\"start\",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,i){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,i)},e),this._spin(t*this.options.step,i)},_spin:function(e,t){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+e*this._increment(this.counter)),this.spinning&&this._trigger(\"spin\",t,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(t){var i=this.options.incremental;return i?e.isFunction(i)?i(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=\"\"+e,i=t.indexOf(\".\");return-1===i?0:t.length-i-1},_adjustValue:function(e){var t,i,s=this.options;return t=null!==s.min?s.min:0,i=e-t,i=Math.round(i/s.step)*s.step,e=t+i,e=parseFloat(e.toFixed(this._precision())),null!==s.max&&e>s.max?s.max:null!==s.min&&s.min>e?s.min:e},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger(\"stop\",e))},_setOption:function(e,t){if(\"culture\"===e||\"numberFormat\"===e){var i=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(i)),void 0}(\"max\"===e||\"min\"===e||\"step\"===e)&&\"string\"==typeof t&&(t=this._parse(t)),\"icons\"===e&&(this.buttons.first().find(\".ui-icon\").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(\".ui-icon\").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),\"disabled\"===e&&(this.widget().toggleClass(\"ui-state-disabled\",!!t),this.element.prop(\"disabled\",!!t),this.buttons.button(t?\"disable\":\"enable\"))},_setOptions:h(function(e){this._super(e)}),_parse:function(e){return\"string\"==typeof e&&\"\"!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),\"\"===e||isNaN(e)?null:e},_format:function(e){return\"\"===e?\"\":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({\"aria-valuemin\":this.options.min,\"aria-valuemax\":this.options.max,\"aria-valuenow\":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var i;\"\"!==e&&(i=this._parse(e),null!==i&&(t||(i=this._adjustValue(i)),e=this._format(i))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass(\"ui-spinner-input\").prop(\"disabled\",!1).removeAttr(\"autocomplete\").removeAttr(\"role\").removeAttr(\"aria-valuemin\").removeAttr(\"aria-valuemax\").removeAttr(\"aria-valuenow\"),this.uiSpinner.replaceWith(this.element)},stepUp:h(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:h(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:h(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:h(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(h(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget(\"ui.tabs\",{version:\"1.11.4\",delay:300,options:{active:null,collapsible:!1,event:\"click\",heightStyle:\"content\",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var i,s;t=t.cloneNode(!1),i=t.href.replace(e,\"\"),s=location.href.replace(e,\"\");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return t.hash.length>1&&i===s}}(),_create:function(){var t=this,i=this.options;this.running=!1,this.element.addClass(\"ui-tabs ui-widget ui-widget-content ui-corner-all\").toggleClass(\"ui-tabs-collapsible\",i.collapsible),this._processTabs(),i.active=this._initialActive(),e.isArray(i.disabled)&&(i.disabled=e.unique(i.disabled.concat(e.map(this.tabs.filter(\".ui-state-disabled\"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):e(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var t=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===t&&(s&&this.tabs.each(function(i,n){return e(n).attr(\"aria-controls\")===s?(t=i,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(\".ui-tabs-active\"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=i?!1:0)),!i&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var i=e(this.document[0].activeElement).closest(\"li\"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:s++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:n=!1,s--;break;case e.ui.keyCode.END:s=this.anchors.length-1;break;case e.ui.keyCode.HOME:s=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),t.ctrlKey||t.metaKey||(i.attr(\"aria-selected\",\"false\"),this.tabs.eq(s).attr(\"aria-selected\",\"true\"),this.activating=this._delay(function(){this.option(\"active\",s)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,i){function s(){return t>n&&(t=0),0>t&&(t=n),t}for(var n=this.tabs.length-1;-1!==e.inArray(s(),this.options.disabled);)t=i?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return\"active\"===e?(this._activate(t),void 0):\"disabled\"===e?(this._setupDisabled(t),void 0):(this._super(e,t),\"collapsible\"===e&&(this.element.toggleClass(\"ui-tabs-collapsible\",t),t||this.options.active!==!1||this._activate(0)),\"event\"===e&&this._setupEvents(t),\"heightStyle\"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!\"$%&'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g,\"\\\\$&\"):\"\"},refresh:function(){var t=this.options,i=this.tablist.children(\":has(a[href])\");t.disabled=e.map(i.filter(\".ui-state-disabled\"),function(e){return i.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({\"aria-selected\":\"false\",\"aria-expanded\":\"false\",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({\"aria-hidden\":\"true\"}),this.active.length?(this.active.addClass(\"ui-tabs-active ui-state-active\").attr({\"aria-selected\":\"true\",\"aria-expanded\":\"true\",tabIndex:0}),this._getPanelForTab(this.active).show().attr({\"aria-hidden\":\"false\"})):this.tabs.eq(0).attr(\"tabIndex\",0)},_processTabs:function(){var t=this,i=this.tabs,s=this.anchors,n=this.panels;\nthis.tablist=this._getList().addClass(\"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\").attr(\"role\",\"tablist\").delegate(\"> li\",\"mousedown\"+this.eventNamespace,function(t){e(this).is(\".ui-state-disabled\")&&t.preventDefault()}).delegate(\".ui-tabs-anchor\",\"focus\"+this.eventNamespace,function(){e(this).closest(\"li\").is(\".ui-state-disabled\")&&this.blur()}),this.tabs=this.tablist.find(\"> li:has(a[href])\").addClass(\"ui-state-default ui-corner-top\").attr({role:\"tab\",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e(\"a\",this)[0]}).addClass(\"ui-tabs-anchor\").attr({role:\"presentation\",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr(\"id\"),h=e(s).closest(\"li\"),l=h.attr(\"aria-controls\");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr(\"aria-controls\")||e({}).uniqueId()[0].id,n=\"#\"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr(\"aria-live\",\"polite\")),a.length&&(t.panels=t.panels.add(a)),l&&h.data(\"ui-tabs-aria-controls\",l),h.attr({\"aria-controls\":o,\"aria-labelledby\":r}),a.attr(\"aria-labelledby\",r)}),this.panels.addClass(\"ui-tabs-panel ui-widget-content ui-corner-bottom\").attr(\"role\",\"tabpanel\"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find(\"ol,ul\").eq(0)},_createPanel:function(t){return e(\"<div>\").attr(\"id\",t).addClass(\"ui-tabs-panel ui-widget-content ui-corner-bottom\").data(\"ui-tabs-destroy\",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var i,s=0;i=this.tabs[s];s++)t===!0||-1!==e.inArray(s,t)?e(i).addClass(\"ui-state-disabled\").attr(\"aria-disabled\",\"true\"):e(i).removeClass(\"ui-state-disabled\").removeAttr(\"aria-disabled\");this.options.disabled=t},_setupEvents:function(t){var i={};t&&e.each(t.split(\" \"),function(e,t){i[t]=\"_eventHandler\"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:\"_tabKeydown\"}),this._on(this.panels,{keydown:\"_panelKeydown\"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,s=this.element.parent();\"fill\"===t?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(\":visible\").each(function(){var t=e(this),s=t.css(\"position\");\"absolute\"!==s&&\"fixed\"!==s&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css(\"overflow\",\"auto\")):\"auto\"===t&&(i=0,this.panels.each(function(){i=Math.max(i,e(this).height(\"\").height())}).height(i))},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n.closest(\"li\"),o=a[0]===s[0],r=o&&i.collapsible,h=r?e():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):e(),u={oldTab:s,oldPanel:l,newTab:r?e():a,newPanel:h};t.preventDefault(),a.hasClass(\"ui-state-disabled\")||a.hasClass(\"ui-tabs-loading\")||this.running||o&&!i.collapsible||this._trigger(\"beforeActivate\",t,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?e():a,this.xhr&&this.xhr.abort(),l.length||h.length||e.error(\"jQuery UI Tabs: Mismatching fragment identifier.\"),h.length&&this.load(this.tabs.index(a),t),this._toggle(t,u))},_toggle:function(t,i){function s(){a.running=!1,a._trigger(\"activate\",t,i)}function n(){i.newTab.closest(\"li\").addClass(\"ui-tabs-active ui-state-active\"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest(\"li\").removeClass(\"ui-tabs-active ui-state-active\"),n()}):(i.oldTab.closest(\"li\").removeClass(\"ui-tabs-active ui-state-active\"),r.hide(),n()),r.attr(\"aria-hidden\",\"true\"),i.oldTab.attr({\"aria-selected\":\"false\",\"aria-expanded\":\"false\"}),o.length&&r.length?i.oldTab.attr(\"tabIndex\",-1):o.length&&this.tabs.filter(function(){return 0===e(this).attr(\"tabIndex\")}).attr(\"tabIndex\",-1),o.attr(\"aria-hidden\",\"false\"),i.newTab.attr({\"aria-selected\":\"true\",\"aria-expanded\":\"true\",tabIndex:0})},_activate:function(t){var i,s=this._findActive(t);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(\".ui-tabs-anchor\")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return\"string\"==typeof e&&(e=this.anchors.index(this.anchors.filter(\"[href$='\"+e+\"']\"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass(\"ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible\"),this.tablist.removeClass(\"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\").removeAttr(\"role\"),this.anchors.removeClass(\"ui-tabs-anchor\").removeAttr(\"role\").removeAttr(\"tabIndex\").removeUniqueId(),this.tablist.unbind(this.eventNamespace),this.tabs.add(this.panels).each(function(){e.data(this,\"ui-tabs-destroy\")?e(this).remove():e(this).removeClass(\"ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel\").removeAttr(\"tabIndex\").removeAttr(\"aria-live\").removeAttr(\"aria-busy\").removeAttr(\"aria-selected\").removeAttr(\"aria-labelledby\").removeAttr(\"aria-hidden\").removeAttr(\"aria-expanded\").removeAttr(\"role\")}),this.tabs.each(function(){var t=e(this),i=t.data(\"ui-tabs-aria-controls\");i?t.attr(\"aria-controls\",i).removeData(\"ui-tabs-aria-controls\"):t.removeAttr(\"aria-controls\")}),this.panels.show(),\"content\"!==this.options.heightStyle&&this.panels.css(\"height\",\"\")},enable:function(t){var i=this.options.disabled;i!==!1&&(void 0===t?i=!1:(t=this._getIndex(t),i=e.isArray(i)?e.map(i,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,i){return i!==t?i:null})),this._setupDisabled(i))},disable:function(t){var i=this.options.disabled;if(i!==!0){if(void 0===t)i=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,i))return;i=e.isArray(i)?e.merge([t],i).sort():[t]}this._setupDisabled(i)}},load:function(t,i){t=this._getIndex(t);var s=this,n=this.tabs.eq(t),a=n.find(\".ui-tabs-anchor\"),o=this._getPanelForTab(n),r={tab:n,panel:o},h=function(e,t){\"abort\"===t&&s.panels.stop(!1,!0),n.removeClass(\"ui-tabs-loading\"),o.removeAttr(\"aria-busy\"),e===s.xhr&&delete s.xhr};this._isLocal(a[0])||(this.xhr=e.ajax(this._ajaxSettings(a,i,r)),this.xhr&&\"canceled\"!==this.xhr.statusText&&(n.addClass(\"ui-tabs-loading\"),o.attr(\"aria-busy\",\"true\"),this.xhr.done(function(e,t,n){setTimeout(function(){o.html(e),s._trigger(\"load\",i,r),h(n,t)},1)}).fail(function(e,t){setTimeout(function(){h(e,t)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr(\"href\"),beforeSend:function(t,a){return n._trigger(\"beforeLoad\",i,e.extend({jqXHR:t,ajaxSettings:a},s))}}},_getPanelForTab:function(t){var i=e(t).attr(\"aria-controls\");return this.element.find(this._sanitizeSelector(\"#\"+i))}}),e.widget(\"ui.tooltip\",{version:\"1.11.4\",options:{content:function(){var t=e(this).attr(\"title\")||\"\";return e(\"<a>\").text(t).html()},hide:!0,items:\"[title]:not([disabled])\",position:{my:\"left top+15\",at:\"left bottom\",collision:\"flipfit flip\"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,i){var s=(t.attr(\"aria-describedby\")||\"\").split(/\\s+/);s.push(i),t.data(\"ui-tooltip-id\",i).attr(\"aria-describedby\",e.trim(s.join(\" \")))},_removeDescribedBy:function(t){var i=t.data(\"ui-tooltip-id\"),s=(t.attr(\"aria-describedby\")||\"\").split(/\\s+/),n=e.inArray(i,s);-1!==n&&s.splice(n,1),t.removeData(\"ui-tooltip-id\"),s=e.trim(s.join(\" \")),s?t.attr(\"aria-describedby\",s):t.removeAttr(\"aria-describedby\")},_create:function(){this._on({mouseover:\"open\",focusin:\"open\"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e(\"<div>\").attr({role:\"log\",\"aria-live\":\"assertive\",\"aria-relevant\":\"additions\"}).addClass(\"ui-helper-hidden-accessible\").appendTo(this.document[0].body)},_setOption:function(t,i){var s=this;return\"disabled\"===t?(this[i?\"_disable\":\"_enable\"](),this.options[t]=i,void 0):(this._super(t,i),\"content\"===t&&e.each(this.tooltips,function(e,t){s._updateContent(t.element)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event(\"blur\");n.target=n.currentTarget=s.element[0],t.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is(\"[title]\")&&t.data(\"ui-tooltip-title\",t.attr(\"title\")).removeAttr(\"title\")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data(\"ui-tooltip-title\")&&t.attr(\"title\",t.data(\"ui-tooltip-title\"))})},open:function(t){var i=this,s=e(t?t.target:this.element).closest(this.options.items);s.length&&!s.data(\"ui-tooltip-id\")&&(s.attr(\"title\")&&s.data(\"ui-tooltip-title\",s.attr(\"title\")),s.data(\"ui-tooltip-open\",!0),t&&\"mouseover\"===t.type&&s.parents().each(function(){var t,s=e(this);s.data(\"ui-tooltip-open\")&&(t=e.Event(\"blur\"),t.target=t.currentTarget=this,i.close(t,!0)),s.attr(\"title\")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr(\"title\")},s.attr(\"title\",\"\"))}),this._registerCloseHandlers(t,s),this._updateContent(s,t))},_updateContent:function(e,t){var i,s=this.options.content,n=this,a=t?t.type:null;return\"string\"==typeof s?this._open(t,e,s):(i=s.call(e[0],function(i){n._delay(function(){e.data(\"ui-tooltip-open\")&&(t&&(t.type=a),this._open(t,e,i))})}),i&&this._open(t,e,i),void 0)},_open:function(t,i,s){function n(e){l.of=e,o.is(\":hidden\")||o.position(l)}var a,o,r,h,l=e.extend({},this.options.position);if(s){if(a=this._find(i))return a.tooltip.find(\".ui-tooltip-content\").html(s),void 0;i.is(\"[title]\")&&(t&&\"mouseover\"===t.type?i.attr(\"title\",\"\"):i.removeAttr(\"title\")),a=this._tooltip(i),o=a.tooltip,this._addDescribedBy(i,o.attr(\"id\")),o.find(\".ui-tooltip-content\").html(s),this.liveRegion.children().hide(),s.clone?(h=s.clone(),h.removeAttr(\"id\").find(\"[id]\").removeAttr(\"id\")):h=s,e(\"<div>\").html(h).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:n}),n(t)):o.position(e.extend({of:i},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){o.is(\":visible\")&&(n(l.of),clearInterval(r))},e.fx.interval)),this._trigger(\"open\",t,{tooltip:o})}},_registerCloseHandlers:function(t,i){var s={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var s=e.Event(t);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),t&&\"mouseover\"!==t.type||(s.mouseleave=\"close\"),t&&\"focusin\"!==t.type||(s.focusout=\"close\"),this._on(!0,i,s)},close:function(t){var i,s=this,n=e(t?t.currentTarget:this.element),a=this._find(n);return a?(i=a.tooltip,a.closing||(clearInterval(this.delayedShow),n.data(\"ui-tooltip-title\")&&!n.attr(\"title\")&&n.attr(\"title\",n.data(\"ui-tooltip-title\")),this._removeDescribedBy(n),a.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(e(this))}),n.removeData(\"ui-tooltip-open\"),this._off(n,\"mouseleave focusout keyup\"),n[0]!==this.element[0]&&this._off(n,\"remove\"),this._off(this.document,\"mousemove\"),t&&\"mouseleave\"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr(\"title\",i.title),delete s.parents[t]}),a.closing=!0,this._trigger(\"close\",t,{tooltip:i}),a.hiding||(a.closing=!1)),void 0):(n.removeData(\"ui-tooltip-open\"),void 0)},_tooltip:function(t){var i=e(\"<div>\").attr(\"role\",\"tooltip\").addClass(\"ui-tooltip ui-widget ui-corner-all ui-widget-content \"+(this.options.tooltipClass||\"\")),s=i.uniqueId().attr(\"id\");return e(\"<div>\").addClass(\"ui-tooltip-content\").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[s]={element:t,tooltip:i}},_find:function(e){var t=e.data(\"ui-tooltip-id\");return t?this.tooltips[t]:null},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr(\"id\")]},_destroy:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event(\"blur\"),a=s.element;n.target=n.currentTarget=a[0],t.close(n,!0),e(\"#\"+i).remove(),a.data(\"ui-tooltip-title\")&&(a.attr(\"title\")||a.attr(\"title\",a.data(\"ui-tooltip-title\")),a.removeData(\"ui-tooltip-title\"))}),this.liveRegion.remove()}})});"
  },
  {
    "path": "lib/capybara/spec/public/jquery.js",
    "content": "/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */\n!function(a,b){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m=\"1.12.4\",n=function(a,b){return new n.fn.init(a,b)},o=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,p=/^-ms-/,q=/-([\\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:\"\",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for(\"boolean\"==typeof g&&(j=g,g=arguments[h]||{},h++),\"object\"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:\"jQuery\"+(m+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return\"function\"===n.type(a)},isArray:Array.isArray||function(a){return\"array\"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||\"object\"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,\"constructor\")&&!k.call(a.constructor.prototype,\"isPrototypeOf\"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+\"\":\"object\"==typeof a||\"function\"==typeof a?i[j.call(a)]||\"object\":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,\"ms-\").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?\"\":(a+\"\").replace(o,\"\")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,\"string\"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return\"string\"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),\"function\"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(a,b){i[\"[object \"+b+\"]\"]=b.toLowerCase()});function s(a){var b=!!a&&\"length\"in a&&a.length,c=n.type(a);return\"function\"===c||n.isWindow(a)?!1:\"array\"===c||0===b||\"number\"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=\"sizzle\"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",L=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",M=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",N=\"\\\\[\"+L+\"*(\"+M+\")(?:\"+L+\"*([*^$|!~]?=)\"+L+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+M+\"))|)\"+L+\"*\\\\]\",O=\":(\"+M+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+N+\")*)|.*)\\\\)|)\",P=new RegExp(L+\"+\",\"g\"),Q=new RegExp(\"^\"+L+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+L+\"+$\",\"g\"),R=new RegExp(\"^\"+L+\"*,\"+L+\"*\"),S=new RegExp(\"^\"+L+\"*([>+~]|\"+L+\")\"+L+\"*\"),T=new RegExp(\"=\"+L+\"*([^\\\\]'\\\"]*?)\"+L+\"*\\\\]\",\"g\"),U=new RegExp(O),V=new RegExp(\"^\"+M+\"$\"),W={ID:new RegExp(\"^#(\"+M+\")\"),CLASS:new RegExp(\"^\\\\.(\"+M+\")\"),TAG:new RegExp(\"^(\"+M+\"|[*])\"),ATTR:new RegExp(\"^\"+N),PSEUDO:new RegExp(\"^\"+O),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+L+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+L+\"*(?:([+-]|)\"+L+\"*(\\\\d+)|))\"+L+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+K+\")$\",\"i\"),needsContext:new RegExp(\"^\"+L+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+L+\"*((?:-\\\\d)?\\\\d*)\"+L+\"*\\\\)|)(?=[^-]|$)\",\"i\")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\\d$/i,Z=/^[^{]+\\{\\s*\\[native \\w/,$=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,_=/[+~]/,aa=/'|\\\\/g,ba=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+L+\"?|(\"+L+\")|.)\",\"ig\"),ca=function(a,b,c){var d=\"0x\"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],\"string\"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+\" \"]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if(\"object\"!==b.nodeName.toLowerCase()){(k=b.getAttribute(\"id\"))?k=k.replace(aa,\"\\\\$&\"):b.setAttribute(\"id\",k=u),r=g(a),h=r.length,l=V.test(k)?\"#\"+k:\"[id='\"+k+\"']\";while(h--)r[h]=l+\" \"+qa(r[h]);s=r.join(\",\"),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute(\"id\")}}}return i(a.replace(Q,\"$1\"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+\" \")>d.cacheLength&&delete b[a.shift()],b[c+\" \"]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement(\"div\");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split(\"|\"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return\"input\"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return(\"input\"===c||\"button\"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&\"undefined\"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?\"HTML\"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener(\"unload\",da,!1):e.attachEvent&&e.attachEvent(\"onunload\",da)),c.attributes=ia(function(a){return a.className=\"i\",!a.getAttribute(\"className\")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment(\"\")),!a.getElementsByTagName(\"*\").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(\"undefined\"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute(\"id\")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c=\"undefined\"!=typeof a.getAttributeNode&&a.getAttributeNode(\"id\");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return\"undefined\"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if(\"*\"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return\"undefined\"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML=\"<a id='\"+u+\"'></a><select id='\"+u+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",a.querySelectorAll(\"[msallowcapture^='']\").length&&q.push(\"[*^$]=\"+L+\"*(?:''|\\\"\\\")\"),a.querySelectorAll(\"[selected]\").length||q.push(\"\\\\[\"+L+\"*(?:value|\"+K+\")\"),a.querySelectorAll(\"[id~=\"+u+\"-]\").length||q.push(\"~=\"),a.querySelectorAll(\":checked\").length||q.push(\":checked\"),a.querySelectorAll(\"a#\"+u+\"+*\").length||q.push(\".#.+[+~]\")}),ia(function(a){var b=n.createElement(\"input\");b.setAttribute(\"type\",\"hidden\"),a.appendChild(b).setAttribute(\"name\",\"D\"),a.querySelectorAll(\"[name=d]\").length&&q.push(\"name\"+L+\"*[*^$|!~]?=\"),a.querySelectorAll(\":enabled\").length||q.push(\":enabled\",\":disabled\"),a.querySelectorAll(\"*,:x\"),q.push(\",.*:\")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,\"div\"),s.call(a,\"[s!='']:x\"),r.push(\"!=\",O)}),q=q.length&&new RegExp(q.join(\"|\")),r=r.length&&new RegExp(r.join(\"|\")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,\"='$1']\"),c.matchesSelector&&p&&!A[b+\" \"]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c=\"\",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if(\"string\"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||\"\").replace(ba,ca),\"~=\"===a[2]&&(a[3]=\" \"+a[3]+\" \"),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),\"nth\"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*(\"even\"===a[3]||\"odd\"===a[3])),a[5]=+(a[7]+a[8]||\"odd\"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||\"\":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(\")\",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return\"*\"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+\" \"];return b||(b=new RegExp(\"(^|\"+L+\")\"+a+\"(\"+L+\"|$)\"))&&y(a,function(a){return b.test(\"string\"==typeof a.className&&a.className||\"undefined\"!=typeof a.getAttribute&&a.getAttribute(\"class\")||\"\")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?\"!=\"===b:b?(e+=\"\",\"=\"===b?e===c:\"!=\"===b?e!==c:\"^=\"===b?c&&0===e.indexOf(c):\"*=\"===b?c&&e.indexOf(c)>-1:\"$=\"===b?c&&e.slice(-c.length)===c:\"~=\"===b?(\" \"+e.replace(P,\" \")+\" \").indexOf(c)>-1:\"|=\"===b?e===c||e.slice(0,c.length+1)===c+\"-\":!1):!0}},CHILD:function(a,b,c,d,e){var f=\"nth\"!==a.slice(0,3),g=\"last\"!==a.slice(-4),h=\"of-type\"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?\"nextSibling\":\"previousSibling\",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p=\"only\"===a&&!o&&\"nextSibling\"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error(\"unsupported pseudo: \"+a);return e[u]?e(b):e.length>1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,\"$1\"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||\"\")||fa.error(\"unsupported lang: \"+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&\"button\"===a.type||\"button\"===b},text:function(a){var b;return\"input\"===a.nodeName.toLowerCase()&&\"text\"===a.type&&(null==(b=a.getAttribute(\"type\"))||\"text\"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+\" \"];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q,\" \")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d=\"\";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&\"parentNode\"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||\"*\",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[\" \"],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:\" \"===a[i-2].type?\"*\":\"\"})).replace(Q,\"$1\"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s=\"0\",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG(\"*\",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+\" \"];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n=\"function\"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&\"ID\"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split(\"\").sort(B).join(\"\")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement(\"div\"))}),ia(function(a){return a.innerHTML=\"<a href='#'></a>\",\"#\"===a.firstChild.getAttribute(\"href\")})||ja(\"type|href|height|width\",function(a,b,c){return c?void 0:a.getAttribute(b,\"type\"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML=\"<input/>\",a.firstChild.setAttribute(\"value\",\"\"),\"\"===a.firstChild.getAttribute(\"value\")})||ja(\"value\",function(a,b,c){return c||\"input\"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute(\"disabled\")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[\":\"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,y=/^.[^:#\\[\\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if(\"string\"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if(\"string\"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+\" \"+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,\"string\"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,\"string\"==typeof a){if(e=\"<\"===a.charAt(0)&&\">\"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?\"undefined\"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||\"string\"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?\"string\"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,\"parentNode\")},parentsUntil:function(a,b,c){return u(a,\"parentNode\",c)},next:function(a){return F(a,\"nextSibling\")},prev:function(a){return F(a,\"previousSibling\")},nextAll:function(a){return u(a,\"nextSibling\")},prevAll:function(a){return u(a,\"previousSibling\")},nextUntil:function(a,b,c){return u(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return u(a,\"previousSibling\",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,\"iframe\")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return\"Until\"!==a.slice(-5)&&(d=c),d&&\"string\"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a=\"string\"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:\"\")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&\"string\"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c=\"\",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[[\"resolve\",\"done\",n.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",n.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",n.Callbacks(\"memory\")]],c=\"pending\",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+\"With\"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+\"With\"](this===e?d:this,arguments),this},e[f[0]+\"With\"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler(\"ready\"),n(d).off(\"ready\"))))}});function J(){d.addEventListener?(d.removeEventListener(\"DOMContentLoaded\",K),a.removeEventListener(\"load\",K)):(d.detachEvent(\"onreadystatechange\",K),a.detachEvent(\"onload\",K))}function K(){(d.addEventListener||\"load\"===a.event.type||\"complete\"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),\"complete\"===d.readyState||\"loading\"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener(\"DOMContentLoaded\",K),a.addEventListener(\"load\",K);else{d.attachEvent(\"onreadystatechange\",K),a.attachEvent(\"onload\",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll(\"left\")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst=\"0\"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName(\"body\")[0],c&&c.style&&(b=d.createElement(\"div\"),e=d.createElement(\"div\"),e.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",c.appendChild(e).appendChild(b),\"undefined\"!=typeof b.style.zoom&&(b.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement(\"div\");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+\" \").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute(\"classid\")===b},N=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d=\"data-\"+b.replace(O,\"-$1\").toLowerCase();if(c=a.getAttribute(d),\"string\"==typeof c){try{c=\"true\"===c?!0:\"false\"===c?!1:\"null\"===c?null:+c+\"\"===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0;\n}return c}function Q(a){var b;for(b in a)if((\"data\"!==b||!n.isEmptyObject(a[b]))&&\"toJSON\"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||\"string\"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),\"object\"!=typeof b&&\"function\"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),\"string\"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(\" \")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,\"parsedAttrs\"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf(\"data-\")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,\"parsedAttrs\",!0)}return e}return\"object\"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||\"fx\")+\"queue\",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||\"fx\";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks(\"once memory\").add(function(){n._removeData(a,b+\"queue\"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),\"fx\"===a&&\"inprogress\"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};\"string\"!=typeof a&&(b=a,a=void 0),a=a||\"fx\";while(g--)c=n._data(f[g],a+\"queueHooks\"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName(\"body\")[0],c&&c.style?(b=d.createElement(\"div\"),e=d.createElement(\"div\"),e.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",c.appendChild(e).appendChild(b),\"undefined\"!=typeof b.style.zoom&&(b.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",b.appendChild(d.createElement(\"div\")).style.width=\"5px\",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,U=new RegExp(\"^(?:([+-])=|)(\"+T+\")([a-z%]*)$\",\"i\"),V=[\"Top\",\"Right\",\"Bottom\",\"Left\"],W=function(a,b){return a=b||a,\"none\"===n.css(a,\"display\")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,\"\")},i=h(),j=c&&c[3]||(n.cssNumber[b]?\"\":\"px\"),k=(n.cssNumber[b]||\"px\"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||\".5\",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\\w:-]+)/,_=/^$|\\/(?:java|ecma)script/i,aa=/^\\s+/,ba=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";function ca(a){var b=ba.split(\"|\"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement(\"div\"),b=d.createDocumentFragment(),c=d.createElement(\"input\");a.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName(\"tbody\").length,l.htmlSerialize=!!a.getElementsByTagName(\"link\").length,l.html5Clone=\"<:nav></:nav>\"!==d.createElement(\"nav\").cloneNode(!0).outerHTML,c.type=\"checkbox\",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML=\"<textarea>x</textarea>\",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement(\"input\"),c.setAttribute(\"type\",\"radio\"),c.setAttribute(\"checked\",\"checked\"),c.setAttribute(\"name\",\"t\"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],area:[1,\"<map>\",\"</map>\"],param:[1,\"<object>\",\"</object>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:l.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f=\"undefined\"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||\"*\"):\"undefined\"!=typeof a.querySelectorAll?a.querySelectorAll(b||\"*\"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,\"globalEval\",!b||n._data(b[d],\"globalEval\"))}var ga=/<|&#?\\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if(\"object\"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement(\"div\")),j=($.exec(g)||[\"\",\"\"])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g=\"table\"!==j||ha.test(g)?\"<table>\"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],\"tbody\")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent=\"\";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,\"input\"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),\"script\"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||\"\")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement(\"div\");for(b in{submit:!0,change:!0,focusin:!0})c=\"on\"+b,(l[b]=c in a)||(e.setAttribute(c,\"t\"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if(\"object\"==typeof b){\"string\"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&(\"string\"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return\"undefined\"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||\"\").match(G)||[\"\"],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||\"\").split(\".\").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(\".\")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent(\"on\"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||\"\").match(G)||[\"\"],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp(\"(^|\\\\.)\"+p.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&(\"**\"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,\"events\"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,\"type\")?b.type:b,r=k.call(b,\"namespace\")?b.namespace.split(\".\"):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(\".\")>-1&&(r=q.split(\".\"),q=r.shift(),r.sort()),h=q.indexOf(\":\")<0&&\"on\"+q,b=b[n.expando]?b:new n.Event(q,\"object\"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join(\".\"),b.rnamespace=b.namespace?new RegExp(\"(^|\\\\.)\"+r.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,\"events\")||{})[b.type]&&n._data(i,\"handle\"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,\"events\")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(\"click\"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||\"click\"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+\" \",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:\"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:\"focusin\"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:\"focusout\"},click:{trigger:function(){return n.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,\"a\")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d=\"on\"+b;a.detachEvent&&(\"undefined\"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,\"form\")?!1:void n.event.add(this,\"click._submit keypress._submit\",function(a){var b=a.target,c=n.nodeName(b,\"input\")||n.nodeName(b,\"button\")?n.prop(b,\"form\"):void 0;c&&!n._data(c,\"submit\")&&(n.event.add(c,\"submit._submit\",function(a){a._submitBubble=!0}),n._data(c,\"submit\",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate(\"submit\",this.parentNode,a))},teardown:function(){return n.nodeName(this,\"form\")?!1:void n.event.remove(this,\"._submit\")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(n.event.add(this,\"propertychange._change\",function(a){\"checked\"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,\"click._change\",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate(\"change\",this,a)})),!1):void n.event.add(this,\"beforeactivate._change\",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,\"change\")&&(n.event.add(b,\"change._change\",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate(\"change\",this.parentNode,a)}),n._data(b,\"change\",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||\"radio\"!==b.type&&\"checkbox\"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,\"._change\"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+\".\"+d.namespace:d.origType,d.selector,d.handler),this;if(\"object\"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&\"function\"!=typeof b||(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\\d+=\"(?:null|\\d+)\"/g,ua=new RegExp(\"<(?:\"+ba+\")[\\\\s/>]\",\"i\"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,wa=/<script|<style|<link/i,xa=/checked\\s*(?:[^=]|=\\s*.checked.)/i,ya=/^true\\/(.*)/,za=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement(\"div\"));function Ca(a,b){return n.nodeName(a,\"table\")&&n.nodeName(11!==b.nodeType?b:b.firstChild,\"tr\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function Da(a){return a.type=(null!==n.find.attr(a,\"type\"))+\"/\"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute(\"type\"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}\"script\"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):\"object\"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):\"input\"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):\"option\"===c?b.defaultSelected=b.selected=a.defaultSelected:\"input\"!==c&&\"textarea\"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&\"string\"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,\"script\"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,\"script\"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||\"\")&&!n._data(g,\"globalEval\")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||\"\").replace(za,\"\")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,\"script\")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,\"<$1></$2>\")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test(\"<\"+a.nodeName+\">\")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,\"script\"),d.length>0&&fa(d,!i&&ea(a,\"script\")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||\"undefined\"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,\"select\")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,\"\"):void 0;if(\"string\"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:\"block\",BODY:\"block\"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],\"display\");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),\"none\"!==c&&c||(Ja=(Ja||n(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp(\"^(\"+T+\")(?!px)[a-z%]+$\",\"i\"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement(\"div\"),j=d.createElement(\"div\");if(j.style){j.style.cssText=\"float:left;opacity:.5\",l.opacity=\"0.5\"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip=\"content-box\",j.cloneNode(!0).style.backgroundClip=\"\",l.clearCloneStyle=\"content-box\"===j.style.backgroundClip,i=d.createElement(\"div\"),i.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",j.innerHTML=\"\",i.appendChild(j),l.boxSizing=\"\"===j.style.boxSizing||\"\"===j.style.MozBoxSizing||\"\"===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b=\"1%\"!==(l||{}).top,h=\"2px\"===(l||{}).marginLeft,e=\"4px\"===(l||{width:\"4px\"}).width,j.style.marginRight=\"50%\",c=\"4px\"===(l||{marginRight:\"4px\"}).marginRight,k=j.appendChild(d.createElement(\"div\")),k.style.cssText=j.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",k.style.marginRight=k.style.width=\"0\",j.style.width=\"1px\",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display=\"none\",f=0===j.getClientRects().length,f&&(j.style.display=\"\",j.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",j.childNodes[0].style.borderCollapse=\"separate\",k=j.getElementsByTagName(\"td\"),k[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",f=0===k[0].offsetHeight,f&&(k[0].style.display=\"\",k[1].style.display=\"none\",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,\"\"!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0===g?g:g+\"\"}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left=\"fontSize\"===b?\"1em\":g,g=h.pixelLeft+\"px\",h.left=d,f&&(e.left=f)),void 0===g?g:g+\"\"||\"auto\"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\\([^)]*\\)/i,Wa=/opacity\\s*=\\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp(\"^(\"+T+\")(.*)$\",\"i\"),Za={position:\"absolute\",visibility:\"hidden\",display:\"block\"},$a={letterSpacing:\"0\",fontWeight:\"400\"},_a=[\"Webkit\",\"O\",\"Moz\",\"ms\"],ab=d.createElement(\"div\").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,\"olddisplay\"),c=d.style.display,b?(f[g]||\"none\"!==c||(d.style.display=\"\"),\"\"===d.style.display&&W(d)&&(f[g]=n._data(d,\"olddisplay\",Ma(d.nodeName)))):(e=W(d),(c&&\"none\"!==c||!e)&&n._data(d,\"olddisplay\",e?c:n.css(d,\"display\"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&\"none\"!==d.style.display&&\"\"!==d.style.display||(d.style.display=b?f[g]||\"\":\"none\"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||\"px\"):b}function eb(a,b,c,d,e){for(var f=c===(d?\"border\":\"content\")?4:\"width\"===b?1:0,g=0;4>f;f+=2)\"margin\"===c&&(g+=n.css(a,c+V[f],!0,e)),d?(\"content\"===c&&(g-=n.css(a,\"padding\"+V[f],!0,e)),\"margin\"!==c&&(g-=n.css(a,\"border\"+V[f]+\"Width\",!0,e))):(g+=n.css(a,\"padding\"+V[f],!0,e),\"padding\"!==c&&(g+=n.css(a,\"border\"+V[f]+\"Width\",!0,e)));return g}function fb(a,b,c){var d=!0,e=\"width\"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&\"border-box\"===n.css(a,\"boxSizing\",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?\"border\":\"content\"),d,f)+\"px\"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,\"opacity\");return\"\"===c?\"1\":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":l.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&\"get\"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,\"string\"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f=\"number\"),null!=c&&c===c&&(\"number\"===f&&(c+=e&&e[3]||(n.cssNumber[h]?\"\":\"px\")),l.clearCloneStyle||\"\"!==c||0!==b.indexOf(\"background\")||(i[b]=\"inherit\"),!(g&&\"set\"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&\"get\"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),\"normal\"===f&&b in $a&&(f=$a[b]),\"\"===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each([\"height\",\"width\"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,\"display\"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&\"border-box\"===n.css(a,\"boxSizing\",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||\"\")?.01*parseFloat(RegExp.$1)+\"\":b?\"1\":\"\"},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?\"alpha(opacity=\"+100*b+\")\":\"\",f=d&&d.filter||c.filter||\"\";c.zoom=1,(b>=1||\"\"===b)&&\"\"===n.trim(f.replace(Va,\"\"))&&c.removeAttribute&&(c.removeAttribute(\"filter\"),\"\"===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+\" \"+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:\"inline-block\"},Sa,[a,\"marginRight\"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,\"marginLeft\"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{\nmarginLeft:0},function(){return a.getBoundingClientRect().left}):0))+\"px\":void 0}),n.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f=\"string\"==typeof c?c.split(\" \"):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return\"boolean\"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?\"\":\"px\")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,\"\"),b&&\"auto\"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:\"swing\"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d[\"margin\"+c]=d[\"padding\"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners[\"*\"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,\"fxshow\");c.queue||(h=n._queueHooks(a,\"fx\"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,\"fx\").length||h.empty.fire()})})),1===a.nodeType&&(\"height\"in b||\"width\"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,\"display\"),k=\"none\"===j?n._data(a,\"olddisplay\")||Ma(a.nodeName):j,\"inline\"===k&&\"none\"===n.css(a,\"float\")&&(l.inlineBlockNeedsLayout&&\"inline\"!==Ma(a.nodeName)?p.zoom=1:p.display=\"inline-block\")),c.overflow&&(p.overflow=\"hidden\",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||\"toggle\"===e,e===(q?\"hide\":\"show\")){if(\"show\"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))\"inline\"===(\"none\"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?\"hidden\"in r&&(q=r.hidden):r=n._data(a,\"fxshow\",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,\"fxshow\");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start=\"width\"===d||\"height\"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&\"expand\"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{\"*\":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=[\"*\"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&\"object\"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:\"number\"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue=\"fx\"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,\"finish\"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return\"string\"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||\"fx\",[]),this.each(function(){var b=!0,e=null!=a&&a+\"queueHooks\",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||\"fx\"),this.each(function(){var b,c=n._data(this),d=c[a+\"queue\"],e=c[a+\"queueHooks\"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each([\"toggle\",\"show\",\"hide\"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||\"boolean\"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb(\"show\"),slideUp:mb(\"hide\"),slideToggle:mb(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||\"fx\",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement(\"input\"),c=d.createElement(\"div\"),e=d.createElement(\"select\"),f=e.appendChild(d.createElement(\"option\"));c=d.createElement(\"div\"),c.setAttribute(\"className\",\"t\"),c.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",a=c.getElementsByTagName(\"a\")[0],b.setAttribute(\"type\",\"checkbox\"),c.appendChild(b),a=c.getElementsByTagName(\"a\")[0],a.style.cssText=\"top:1px\",l.getSetAttribute=\"t\"!==c.className,l.style=/top/.test(a.getAttribute(\"style\")),l.hrefNormalized=\"/a\"===a.getAttribute(\"href\"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement(\"form\").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement(\"input\"),b.setAttribute(\"value\",\"\"),l.input=\"\"===b.getAttribute(\"value\"),b.value=\"t\",b.setAttribute(\"type\",\"radio\"),l.radioValue=\"t\"===b.value}();var rb=/\\r/g,sb=/[\\x20\\t\\r\\n\\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e=\"\":\"number\"==typeof e?e+=\"\":n.isArray(e)&&(e=n.map(e,function(a){return null==a?\"\":a+\"\"})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&\"set\"in b&&void 0!==b.set(this,e,\"value\")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&\"get\"in b&&void 0!==(c=b.get(e,\"value\"))?c:(c=e.value,\"string\"==typeof c?c.replace(rb,\"\"):null==c?\"\":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,\"value\");return null!=b?b:n.trim(n.text(a)).replace(sb,\" \")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f=\"select-one\"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute(\"disabled\"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,\"optgroup\"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each([\"radio\",\"checkbox\"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute(\"value\")?\"on\":a.value})});var tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return\"undefined\"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ub:tb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&\"set\"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+\"\"),c):e&&\"get\"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&\"radio\"===b&&n.nodeName(a,\"input\")){var c=a.value;return a.setAttribute(\"type\",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase(\"default-\"+c)]=a[d]=!1:n.attr(a,c,\"\"),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase(\"default-\"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase(\"default-\"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,\"input\")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+=\"\",\"value\"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&\"\"!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,\"\"===b?!1:b,c)}},n.each([\"width\",\"height\"],function(a,b){n.attrHooks[b]={set:function(a,c){return\"\"===c?(a.setAttribute(b,\"auto\"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+\"\"}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&\"set\"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&\"get\"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,\"tabindex\");return b?parseInt(b,10):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),l.hrefNormalized||n.each([\"href\",\"src\"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype=\"encoding\");var Bb=/[\\t\\r\\n\\f]/g;function Cb(a){return n.attr(a,\"class\")||\"\"}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Cb(this)))});if(\"string\"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(\" \"+e+\" \").replace(Bb,\" \")){g=0;while(f=b[g++])d.indexOf(\" \"+f+\" \")<0&&(d+=f+\" \");h=n.trim(d),e!==h&&n.attr(c,\"class\",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Cb(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(\" \"+e+\" \").replace(Bb,\" \")){g=0;while(f=b[g++])while(d.indexOf(\" \"+f+\" \")>-1)d=d.replace(\" \"+f+\" \",\" \");h=n.trim(d),e!==h&&n.attr(c,\"class\",h)}}return this},toggleClass:function(a,b){var c=typeof a;return\"boolean\"==typeof b&&\"string\"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Cb(this),b),b)}):this.each(function(){var b,d,e,f;if(\"string\"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&\"boolean\"!==c||(b=Cb(this),b&&n._data(this,\"__className__\",b),n.attr(this,\"class\",b||a===!1?\"\":n._data(this,\"__className__\")||\"\"))})},hasClass:function(a){var b,c,d=0;b=\" \"+a+\" \";while(c=this[d++])if(1===c.nodeType&&(\" \"+Cb(c)+\" \").replace(Bb,\" \").indexOf(b)>-1)return!0;return!1}}),n.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Db=a.location,Eb=n.now(),Fb=/\\?/,Gb=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+\"\");var c,d=null,e=n.trim(b+\"\");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,\"\")}))?Function(\"return \"+e)():n.error(\"Invalid JSON: \"+b)},n.parseXML=function(b){var c,d;if(!b||\"string\"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,\"text/xml\")):(c=new a.ActiveXObject(\"Microsoft.XMLDOM\"),c.async=\"false\",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName(\"parsererror\").length||n.error(\"Invalid XML: \"+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\\/\\//,Nb=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Ob={},Pb={},Qb=\"*/\".concat(\"*\"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(a){return function(b,c){\"string\"!=typeof b&&(c=b,b=\"*\");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])\"+\"===d.charAt(0)?(d=d.slice(1)||\"*\",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return\"string\"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e[\"*\"]&&g(\"*\")}function Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while(\"*\"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader(\"Content-Type\"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+\" \"+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if(\"*\"===f)f=i;else if(\"*\"!==i&&i!==f){if(g=j[i+\" \"+f]||j[\"* \"+f],!g)for(e in j)if(h=e.split(\" \"),h[1]===f&&(g=j[i+\" \"+h[0]]||j[\"* \"+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a[\"throws\"])b=g(b);else try{b=g(b)}catch(l){return{state:\"parsererror\",error:g?l:\"No conversion from \"+i+\" to \"+f}}}return{state:\"success\",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rb,type:\"GET\",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Qb,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":n.parseJSON,\"text xml\":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){\"object\"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks(\"once memory\"),r=l.statusCode||{},s={},t={},u=0,v=\"canceled\",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+\"\").replace(Hb,\"\").replace(Mb,Sb[1]+\"//\"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||\"*\").toLowerCase().match(G)||[\"\"],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||(\"http:\"===d[1]?\"80\":\"443\"))===(Sb[3]||(\"http:\"===Sb[1]?\"80\":\"443\")))),l.data&&l.processData&&\"string\"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger(\"ajaxStart\"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?\"&\":\"?\")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,\"$1_=\"+Eb++):f+(Fb.test(f)?\"&\":\"?\")+\"_=\"+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader(\"If-Modified-Since\",n.lastModified[f]),n.etag[f]&&w.setRequestHeader(\"If-None-Match\",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader(\"Content-Type\",l.contentType),w.setRequestHeader(\"Accept\",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(\"*\"!==l.dataTypes[0]?\", \"+Qb+\"; q=0.01\":\"\"):l.accepts[\"*\"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v=\"abort\";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger(\"ajaxSend\",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort(\"timeout\")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,\"No Transport\");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||\"\",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader(\"Last-Modified\"),x&&(n.lastModified[f]=x),x=w.getResponseHeader(\"etag\"),x&&(n.etag[f]=x)),204===b||\"HEAD\"===l.type?y=\"nocontent\":304===b?y=\"notmodified\":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y=\"error\",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+\"\",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?\"ajaxSuccess\":\"ajaxError\",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger(\"ajaxComplete\",[w,l]),--n.active||n.event.trigger(\"ajaxStop\")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,\"json\")},getScript:function(a,b){return n.get(a,void 0,b,\"script\")}}),n.each([\"get\",\"post\"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,\"body\")||n(this).replaceWith(this.childNodes)}).end()}});function Yb(a){return a.style&&a.style.display||n.css(a,\"display\")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if(\"none\"===Yb(a)||\"hidden\"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\\[\\]$/,ac=/\\r?\\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(a+\"[\"+(\"object\"==typeof e&&null!=e?b:\"\")+\"]\",e,c,d)});else if(c||\"object\"!==n.type(b))d(a,b);else for(e in b)dc(a+\"[\"+e+\"]\",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?\"\":b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)dc(c,a[c],b,e);return d.join(\"&\").replace($b,\"+\")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,\"elements\");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(\":disabled\")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(ac,\"\\r\\n\")}}):{name:b.name,value:c.replace(ac,\"\\r\\n\")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent(\"onunload\",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&\"withCredentials\"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d[\"X-Requested-With\"]||(d[\"X-Requested-With\"]=\"XMLHttpRequest\");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+\"\");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,\"string\"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=\"\"}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(b){}}n.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter(\"script\",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\",a.global=!1)}),n.ajaxTransport(\"script\",function(a){if(a.crossDomain){var b,c=d.head||n(\"head\")[0]||d.documentElement;return{send:function(e,f){b=d.createElement(\"script\"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,\"success\"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\\?(?=&|$)|\\?\\?/;n.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var a=jc.pop()||n.expando+\"_\"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?\"url\":\"string\"==typeof b.data&&0===(b.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&kc.test(b.data)&&\"data\");return h||\"jsonp\"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(kc,\"$1\"+e):b.jsonp!==!1&&(b.url+=(Fb.test(b.url)?\"&\":\"?\")+b.jsonp+\"=\"+e),b.converters[\"script json\"]=function(){return g||n.error(e+\" was not called\"),g[0]},b.dataTypes[0]=\"json\",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,jc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),\"script\"):void 0}),n.parseHTML=function(a,b,c){if(!a||\"string\"!=typeof a)return null;\"boolean\"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if(\"string\"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(\" \");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&\"object\"==typeof b&&(e=\"POST\"),g.length>0&&n.ajax({url:a,type:e||\"GET\",dataType:\"html\",data:b}).done(function(a){f=arguments,g.html(d?n(\"<div>\").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,\"position\"),l=n(a),m={};\"static\"===k&&(a.style.position=\"relative\"),h=l.offset(),f=n.css(a,\"top\"),i=n.css(a,\"left\"),j=(\"absolute\"===k||\"fixed\"===k)&&n.inArray(\"auto\",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),\"using\"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(\"undefined\"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return\"fixed\"===n.css(d,\"position\")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],\"html\")||(c=a.offset()),c.top+=n.css(a[0],\"borderTopWidth\",!0),c.left+=n.css(a[0],\"borderLeftWidth\",!0)),{top:b.top-c.top-n.css(d,\"marginTop\",!0),left:b.left-c.left-n.css(d,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,\"html\")&&\"static\"===n.css(a,\"position\"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each([\"top\",\"left\"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+\"px\":c):void 0})}),n.each({Height:\"height\",Width:\"width\"},function(a,b){n.each({\npadding:\"inner\"+a,content:b,\"\":\"outer\"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||\"boolean\"!=typeof d),g=c||(d===!0||e===!0?\"margin\":\"border\");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement[\"client\"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body[\"scroll\"+a],e[\"scroll\"+a],b.body[\"offset\"+a],e[\"offset\"+a],e[\"client\"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,\"**\"):this.off(b,a||\"**\",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});\n"
  },
  {
    "path": "lib/capybara/spec/public/offset.js",
    "content": "$(function() {\n  $(document).on('click dblclick contextmenu', function(e){\n    e.preventDefault();\n    $(document.body).append('<div id=\"has-been-clicked\">Has been clicked at ' + e.clientX + ',' + e.clientY + '</div>');\n  })\n})"
  },
  {
    "path": "lib/capybara/spec/public/test.js",
    "content": "var activeRequests = 0;\n$(function() {\n  $('#change').text('I changed it');\n  $('#drag, #drag_scroll, #drag_link').draggable({\n    start: function(event, ui){\n      $(document.body).append(\n        \"<div class='drag_start'>Dragged!\" +\n          (event.altKey ? \"-alt\" : \"\") +\n          (event.ctrlKey ? \"-ctrl\" : \"\") +\n          (event.metaKey ? \"-meta\" : \"\") +\n          (event.shiftKey ? \"-shift\" : \"\") +\n          \"</div>\"\n      );\n    }\n  });\n  $('#drop, #drop_scroll').droppable({\n    tolerance: 'touch',\n    drop: function(event, ui) {\n      ui.draggable.remove();\n      $(this).html(\n        \"Dropped!\" +\n          (event.altKey ? \"-alt\" : \"\") +\n          (event.ctrlKey ? \"-ctrl\" : \"\") +\n          (event.metaKey ? \"-meta\" : \"\") +\n          (event.shiftKey ? \"-shift\" : \"\")\n      );\n    }\n  });\n  $('#drag_html5, #drag_html5_scroll').on('dragstart', function(ev){\n    $(document.body).append(\n        \"<div class='drag_start'>HTML5 Dragged!\" +\n          (event.altKey ? \"-alt\" : \"\") +\n          (event.ctrlKey ? \"-ctrl\" : \"\") +\n          (event.metaKey ? \"-meta\" : \"\") +\n          (event.shiftKey ? \"-shift\" : \"\") +\n          \"</div>\"\n    );\n    ev.originalEvent.dataTransfer.setData(\"text\", ev.target.id);\n  });\n  $('#drag_html5, #drag_html5_scroll').on('dragend', function(ev){\n    $(this).after('<div class=\"log\">DragEnd with client position: ' + ev.clientX + ',' + ev.clientY)\n  });\n  $('#drop_html5, #drop_html5_scroll').on('dragover', function(ev){\n    $(this).after('<div class=\"log\">DragOver with client position: ' + ev.clientX + ',' + ev.clientY)\n    if ($(this).hasClass('drop')) { ev.preventDefault(); }\n  });\n  $('#drop_html5, #drop_html5_scroll').on('dragenter', function(ev){\n    $(this).after('<div class=\"log\">DragEnter')\n    if ($(this).hasClass('drop')) { ev.preventDefault(); }\n  });\n  $('#drop_html5, #drop_html5_scroll').on('dragleave', function(ev){\n    $(this).after('<div class=\"log\">DragLeave with client position: ' + ev.clientX + ',' + ev.clientY)\n    if ($(this).hasClass('drop')) { ev.preventDefault(); }\n  });\n  $('#drop_html5, #drop_html5_scroll').on('drop', function(ev){\n    $(this).after('<div class=\"log\">Drop with client position: ' + ev.clientX + ',' + ev.clientY)\n    if ($(this).hasClass('drop')) { ev.preventDefault(); }\n  });\n  $('#drop_html5, #drop_html5_scroll').on('drop', function(ev){\n    ev.preventDefault();\n    var oev = ev.originalEvent;\n    if (oev.dataTransfer.items) {\n      for (var i = 0; i < oev.dataTransfer.items.length; i++){\n        var item = oev.dataTransfer.items[i];\n        if (item.kind === 'file'){\n          var file = item.getAsFile();\n          $(this).append('HTML5 Dropped file: ' + file.name);\n        } else {\n          var _this = this;\n          var callback = (function(type) {\n            return function(s) {\n              $(_this).append(\n                \"HTML5 Dropped string: \" +\n                  type +\n                  \" \" +\n                  s +\n                  (ev.altKey ? \"-alt\" : \"\") +\n                  (ev.ctrlKey ? \"-ctrl\" : \"\") +\n                  (ev.metaKey ? \"-meta\" : \"\") +\n                  (ev.shiftKey ? \"-shift\" : \"\")\n              );\n            };\n          })(item.type);\n          item.getAsString(callback);\n        }\n      }\n    } else {\n      $(this).html('HTML5 Dropped ' + oev.dataTransfer.getData(\"text\"));\n      for (var i = 0; i < oev.dataTransfer.files.length; i++) {\n        $(this).append('HTML5 Dropped file: ' + oev.dataTransfer.files[i].name);\n      }\n      for (var i = 0; i < oev.dataTransfer.types.length; i++) {\n        var type = oev.dataTransfer.types[i];\n        $(this).append('HTML5 Dropped string: ' + type + ' ' + oev.dataTransfer.getData(type));\n      }\n    }\n  });\n  $('#clickable').click(function(e) {\n    var link = $(this);\n    setTimeout(function() {\n      $(link).after('<a id=\"has-been-clicked\" href=\"#\">Has been clicked</a>');\n      $(link).after('<input type=\"submit\" value=\"New Here\">');\n      $(link).after('<input type=\"text\" id=\"new_field\">');\n      $('#change').remove();\n    }, 1000);\n    return false;\n  });\n  $('#slow-click').click(function() {\n    var link = $(this);\n    setTimeout(function() {\n      $(link).after('<a id=\"slow-clicked\" href=\"#\">Slow link clicked</a>');\n    }, 4000);\n    return false;\n  });\n  $('#aria-button').click(function() {\n    var span = $(this);\n    setTimeout(function() {\n      $(span).after('<span role=\"button\">ARIA button has been clicked</span>')\n    }, 1000);\n    return false;\n  });\n  $('#waiter').change(function() {\n    activeRequests = 1;\n    setTimeout(function() {\n      activeRequests = 0;\n    }, 500);\n  });\n  $('#with_focus_event').focus(function() {\n    $('body').append('<p id=\"focus_event_triggered\">Focus Event triggered</p>');\n  });\n  $('#with_change_event').change(function() {\n    $('body').append($('<p class=\"change_event_triggered\"></p>').text(this.value));\n  });\n  $('#with_change_event').on('input', function() {\n    $('body').append($('<p class=\"input_event_triggered\"></p>').text(this.value));\n  });\n  $('#checkbox_with_event').click(function() {\n    $('body').append('<p id=\"checkbox_event_triggered\">Checkbox event triggered</p>');\n  });\n  $('#fire_ajax_request').click(function() {\n    $.ajax({url: \"/slow_response\", context: document.body, success: function() {\n      $('body').append('<p id=\"ajax_request_done\">Ajax request done</p>');\n    }});\n  });\n  $('#reload-link').click(function() {\n    setTimeout(function() {\n      $('#reload-me').replaceWith('<div id=\"reload-me\"><em><a>has been reloaded</a></em></div>');\n    }, 250)\n  });\n  $('#reload-list').click(function() {\n    setTimeout(function() {\n      $('#the-list').html('<li>Foo</li><li>Bar</li>');\n    }, 550)\n  });\n  $('#change-title').click(function() {\n    setTimeout(function() {\n      $('title').text('changed title')\n    }, 400)\n  });\n  $('#change-size').click(function() {\n    setTimeout(function() {\n      document.getElementById('change').style.fontSize = '50px';\n    }, 500)\n  });\n  $('#click-test').on({\n    click: function(e) {\n      window.click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;\n      var desc = \"\";\n      if (e.altKey) desc += 'alt ';\n      if (e.ctrlKey) desc += 'control ';\n      if (e.metaKey) desc += 'meta ';\n      if (e.shiftKey) desc += 'shift ';\n      var pos = this.getBoundingClientRect();\n      $(this).after('<a id=\"has-been-clicked\" href=\"#\">Has been ' + desc + 'clicked at ' + (e.clientX - pos.left) + ',' + (e.clientY - pos.top) + '</a>');\n    },\n    dblclick: function(e) {\n      var desc = \"\";\n      if (e.altKey) desc += 'alt ';\n      if (e.ctrlKey) desc += 'control ';\n      if (e.metaKey) desc += 'meta ';\n      if (e.shiftKey) desc += 'shift ';\n      var pos = this.getBoundingClientRect();\n      $(this).after('<a id=\"has-been-double-clicked\" href=\"#\">Has been ' + desc + 'double clicked at ' + (e.clientX - pos.left) + ',' + (e.clientY - pos.top) + '</a>');\n    },\n    contextmenu: function(e) {\n      e.preventDefault();\n      var desc = \"\";\n      if (e.altKey) desc += 'alt ';\n      if (e.ctrlKey) desc += 'control ';\n      if (e.metaKey) desc += 'meta ';\n      if (e.shiftKey) desc += 'shift ';\n      var pos = this.getBoundingClientRect();\n      $(this).after('<a id=\"has-been-right-clicked\" href=\"#\">Has been ' + desc + 'right clicked at ' + (e.clientX - pos.left) + ',' + (e.clientY - pos.top) + '</a>');\n    },\n    mousedown: function(e) {\n      window.click_delay = undefined;\n      window.right_click_delay = undefined;\n      window.mouse_down_time = new Date().getTime();\n    },\n    mouseup: function(e) {\n      if (e.button == 2){\n        window.right_click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;\n      }\n    }\n  });\n  $('#open-alert').click(function() {\n    alert('Alert opened [*Yay?*]');\n    $(this).attr('opened', 'true');\n  });\n  $('#open-delayed-alert').click(function() {\n    var link = this;\n    setTimeout(function() {\n      alert('Delayed alert opened');\n      $(link).attr('opened', 'true');\n    }, 250);\n  });\n  $('#open-slow-alert').click(function() {\n    var link = this;\n    setTimeout(function() {\n      alert('Delayed alert opened');\n      $(link).attr('opened', 'true');\n    }, 3000);\n  });\n  $('#alert-page-change').click(function() {\n    alert('Page is changing');\n    return true;\n  });\n  $('#open-confirm').click(function() {\n    if(confirm('Confirm opened')) {\n      $(this).attr('confirmed', 'true');\n    } else {\n      $(this).attr('confirmed', 'false');\n    }\n  });\n  $('#open-prompt').click(function() {\n    var response = prompt('Prompt opened');\n    if(response === null) {\n      $(this).attr('response', 'dismissed');\n    } else {\n      $(this).attr('response', response);\n    }\n  });\n  $('#open-prompt-with-default').click(function() {\n    var response = prompt('Prompt opened', 'Default value!');\n    if(response === null) {\n      $(this).attr('response', 'dismissed');\n    } else {\n      $(this).attr('response', response);\n    }\n  });\n  $('#open-twice').click(function() {\n    if (confirm('Are you sure?')) {\n      if (!confirm('Are you really sure?')) {\n        $(this).attr('confirmed', 'false');\n      }\n    }\n  });\n  $('#delayed-page-change').click(function() {\n    setTimeout(function() {\n      window.location.pathname = '/with_html'\n    }, 500)\n  });\n  $('#with-key-events').keydown(function(e){\n    $('#key-events-output').append('keydown:'+e.which+' ')\n  });\n  $('#disable-on-click').click(function(e){\n    var input = this;\n    setTimeout(function() {\n      input.disabled = true;\n    }, 500)\n  });\n  $('#set-storage').click(function(e){\n    sessionStorage.setItem('session', 'session_value');\n    localStorage.setItem('local', 'local value');\n  });\n  $('#multiple-file, #hidden_file').change(function(e){\n    $('body').append($('<p class=\"file_change\">File input changed</p>'));\n  });\n\n  var shadow = document.querySelector('#shadow').attachShadow({mode: 'open'});\n  var span = document.createElement('span');\n  span.textContent = 'The things we do in the shadows';\n  shadow.appendChild(span);\n});\n"
  },
  {
    "path": "lib/capybara/spec/session/accept_alert_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#accept_alert', requires: [:modals] do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should accept the alert' do\n    @session.accept_alert do\n      @session.click_link('Open alert')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-alert' and @opened='true']\")\n  end\n\n  it 'should accept the alert if the text matches' do\n    @session.accept_alert 'Alert opened' do\n      @session.click_link('Open alert')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-alert' and @opened='true']\")\n  end\n\n  it 'should accept the alert if text contains \"special\" Regex characters' do\n    @session.accept_alert 'opened [*Yay?*]' do\n      @session.click_link('Open alert')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-alert' and @opened='true']\")\n  end\n\n  it 'should accept the alert if the text matches a regexp' do\n    @session.accept_alert(/op.{2}ed/) do\n      @session.click_link('Open alert')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-alert' and @opened='true']\")\n  end\n\n  it 'should not accept the alert if the text doesnt match' do\n    expect do\n      @session.accept_alert 'Incorrect Text' do\n        @session.click_link('Open alert')\n      end\n    end.to raise_error(Capybara::ModalNotFound)\n  end\n\n  it 'should return the message presented' do\n    message = @session.accept_alert do\n      @session.click_link('Open alert')\n    end\n    expect(message).to eq('Alert opened [*Yay?*]')\n  end\n\n  it 'should handle the alert if the page changes' do\n    @session.accept_alert do\n      @session.click_link('Alert page change')\n      sleep 1 # ensure page change occurs before the accept_alert block exits\n    end\n    expect(@session).to have_current_path('/with_html', wait: 5)\n  end\n\n  context 'with an asynchronous alert' do\n    it 'should accept the alert' do\n      @session.accept_alert do\n        @session.click_link('Open delayed alert')\n      end\n      expect(@session).to have_xpath(\"//a[@id='open-delayed-alert' and @opened='true']\")\n    end\n\n    it 'should return the message presented' do\n      message = @session.accept_alert do\n        @session.click_link('Open delayed alert')\n      end\n      expect(message).to eq('Delayed alert opened')\n    end\n\n    it 'should allow to adjust the delay' do\n      @session.accept_alert wait: 10 do\n        @session.click_link('Open slow alert')\n      end\n      expect(@session).to have_xpath(\"//a[@id='open-slow-alert' and @opened='true']\")\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/accept_confirm_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#accept_confirm', requires: [:modals] do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should accept the confirm' do\n    @session.accept_confirm do\n      @session.click_link('Open confirm')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-confirm' and @confirmed='true']\")\n  end\n\n  it 'should return the message presented' do\n    message = @session.accept_confirm do\n      @session.click_link('Open confirm')\n    end\n    expect(message).to eq('Confirm opened')\n  end\n\n  it 'should work with nested modals' do\n    expect do\n      @session.dismiss_confirm 'Are you really sure?' do\n        @session.accept_confirm 'Are you sure?' do\n          @session.click_link('Open check twice')\n        end\n      end\n    end.not_to raise_error\n    expect(@session).to have_xpath(\"//a[@id='open-twice' and @confirmed='false']\")\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/accept_prompt_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#accept_prompt', requires: [:modals] do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should accept the prompt with no message' do\n    @session.accept_prompt do\n      @session.click_link('Open prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt' and @response='']\")\n  end\n\n  it 'should accept the prompt with no message when there is a default' do\n    @session.accept_prompt do\n      @session.click_link('Open defaulted prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt-with-default' and @response='Default value!']\")\n  end\n\n  it 'should return the message presented' do\n    message = @session.accept_prompt do\n      @session.click_link('Open prompt')\n    end\n    expect(message).to eq('Prompt opened')\n  end\n\n  it 'should accept the prompt with a response' do\n    @session.accept_prompt with: 'the response' do\n      @session.click_link('Open prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt' and @response='the response']\")\n  end\n\n  it 'should accept the prompt with a response when there is a default' do\n    @session.accept_prompt with: 'the response' do\n      @session.click_link('Open defaulted prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt-with-default' and @response='the response']\")\n  end\n\n  it 'should accept the prompt with a blank response when there is a default' do\n    @session.accept_prompt with: '' do\n      @session.click_link('Open defaulted prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt-with-default' and @response='']\")\n  end\n\n  it 'should allow special characters in the reponse' do\n    @session.accept_prompt with: '\\'the\\' \\b \"response\"' do\n      @session.click_link('Open prompt')\n    end\n    expect(@session).to have_xpath(%{//a[@id='open-prompt' and @response=concat(\"'the' \", '\\\\b \"response\"')]})\n  end\n\n  it 'should accept the prompt if the message matches' do\n    @session.accept_prompt 'Prompt opened', with: 'matched' do\n      @session.click_link('Open prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt' and @response='matched']\")\n  end\n\n  it \"should not accept the prompt if the message doesn't match\" do\n    expect do\n      @session.accept_prompt 'Incorrect Text', with: 'not matched' do\n        @session.click_link('Open prompt')\n      end\n    end.to raise_error(Capybara::ModalNotFound)\n  end\n\n  it 'should return the message presented' do\n    message = @session.accept_prompt with: 'the response' do\n      @session.click_link('Open prompt')\n    end\n    expect(message).to eq('Prompt opened')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/active_element_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#active_element', requires: [:active_element] do\n  it 'should return the active element' do\n    @session.visit('/form')\n    @session.send_keys(:tab)\n\n    expect(@session.active_element).to match_selector(:css, '[tabindex=\"1\"]')\n\n    @session.send_keys(:tab)\n\n    expect(@session.active_element).to match_selector(:css, '[tabindex=\"2\"]')\n  end\n\n  it 'should support reloading' do\n    @session.visit('/form')\n    expect(@session.active_element).to match_selector(:css, 'body')\n    @session.execute_script <<-JS\n      window.setTimeout(() => {\n        document.querySelector('#form_title').focus();\n      }, 1000)\n    JS\n    expect(@session.active_element).to match_selector(:css, 'body', wait: false)\n    expect(@session.active_element).to match_selector(:css, '#form_title', wait: 2)\n  end\n\n  it 'should return a Capybara::Element' do\n    @session.visit('/form')\n    expect(@session.active_element).to be_a Capybara::Node::Element\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/all_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#all' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should find all elements using the given locator' do\n    expect(@session.all('//p').size).to eq(3)\n    expect(@session.all('//h1').first.text).to eq('This is a test')\n    expect(@session.all(\"//input[@id='test_field']\").first.value).to eq('monkey')\n  end\n\n  it 'should return an empty array when nothing was found' do\n    expect(@session.all('//div[@id=\"nosuchthing\"]')).to be_empty\n  end\n\n  it 'should wait for matching elements to appear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session.all(:css, 'a#has-been-clicked')).not_to be_empty\n  end\n\n  it 'should not wait if `minimum: 0` option is specified', requires: [:js] do\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session.all(:css, 'a#has-been-clicked', minimum: 0)).to be_empty\n  end\n\n  it 'should accept an XPath instance', :exact_false do\n    @session.visit('/form')\n    @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('Name')\n    expect(@xpath).to be_a(XPath::Union)\n    @result = @session.all(@xpath).map(&:value)\n    expect(@result).to include('Smith', 'John', 'John Smith')\n  end\n\n  it 'should allow reversing the order' do\n    @session.visit('/form')\n    fields = @session.all(:fillable_field, 'Name', exact: false).to_a\n    reverse_fields = @session.all(:fillable_field, 'Name', order: :reverse, exact: false).to_a\n    expect(fields).to eq(reverse_fields.reverse)\n  end\n\n  it 'should raise an error when given invalid options' do\n    expect { @session.all('//p', schmoo: 'foo') }.to raise_error(ArgumentError)\n  end\n\n  it 'should not reload by default', requires: [:driver] do\n    paras = @session.all(:css, 'p', minimum: 3)\n    expect { paras[0].text }.not_to raise_error\n    @session.refresh\n    expect { paras[0].text }.to raise_error do |err|\n      expect(err).to be_an_invalid_element_error(@session)\n    end\n  end\n\n  context 'with allow_reload' do\n    it 'should reload if true' do\n      paras = @session.all(:css, 'p', allow_reload: true, minimum: 3)\n      expect { paras[0].text }.not_to raise_error\n      @session.refresh\n      sleep 1 # Ensure page has started to reload\n      expect(paras[0]).to have_text('Lorem ipsum dolor')\n      expect(paras[1]).to have_text('Duis aute irure dolor')\n    end\n\n    it 'should not reload if false', requires: [:driver] do\n      paras = @session.all(:css, 'p', allow_reload: false, minimum: 3)\n      expect { paras[0].text }.not_to raise_error\n      @session.refresh\n      sleep 1 # Ensure page has started to reload\n      expect { paras[0].text }.to raise_error do |err|\n        expect(err).to be_an_invalid_element_error(@session)\n      end\n      expect { paras[2].text }.to raise_error do |err|\n        expect(err).to be_an_invalid_element_error(@session)\n      end\n    end\n  end\n\n  context 'with css selectors' do\n    it 'should find all elements using the given selector' do\n      expect(@session.all(:css, 'h1').first.text).to eq('This is a test')\n      expect(@session.all(:css, \"input[id='test_field']\").first.value).to eq('monkey')\n    end\n\n    it 'should find all elements when given a list of selectors' do\n      expect(@session.all(:css, 'h1, p').size).to eq(4)\n    end\n  end\n\n  context 'with xpath selectors' do\n    it 'should find the first element using the given locator' do\n      expect(@session.all(:xpath, '//h1').first.text).to eq('This is a test')\n      expect(@session.all(:xpath, \"//input[@id='test_field']\").first.value).to eq('monkey')\n    end\n\n    it 'should use alternated regex for :id' do\n      expect(@session.all(:xpath, './/h2', id: /h2/).unfiltered_size).to eq 3\n      expect(@session.all(:xpath, './/h2', id: /h2(one|two)/).unfiltered_size).to eq 2\n    end\n  end\n\n  context 'with css as default selector' do\n    before { Capybara.default_selector = :css }\n\n    it 'should find the first element using the given locator' do\n      expect(@session.all('h1').first.text).to eq('This is a test')\n      expect(@session.all(\"input[id='test_field']\").first.value).to eq('monkey')\n    end\n  end\n\n  context 'with visible filter' do\n    it 'should only find visible nodes when true' do\n      expect(@session.all(:css, 'a.simple', visible: true).size).to eq(1)\n    end\n\n    it 'should find nodes regardless of whether they are invisible when false' do\n      expect(@session.all(:css, 'a.simple', visible: false).size).to eq(2)\n    end\n\n    it 'should default to Capybara.ignore_hidden_elements' do\n      Capybara.ignore_hidden_elements = true\n      expect(@session.all(:css, 'a.simple').size).to eq(1)\n      Capybara.ignore_hidden_elements = false\n      expect(@session.all(:css, 'a.simple').size).to eq(2)\n    end\n\n    context 'with per session config', requires: [:psc] do\n      it 'should use the sessions ignore_hidden_elements', :psc do\n        Capybara.ignore_hidden_elements = true\n        @session.config.ignore_hidden_elements = false\n        expect(Capybara.ignore_hidden_elements).to be(true)\n        expect(@session.all(:css, 'a.simple').size).to eq(2)\n        @session.config.ignore_hidden_elements = true\n        expect(@session.all(:css, 'a.simple').size).to eq(1)\n      end\n    end\n  end\n\n  context 'with obscured filter', requires: [:css] do\n    it 'should only find nodes on top in the viewport when false' do\n      expect(@session.all(:css, 'a.simple', obscured: false).size).to eq(1)\n    end\n\n    it 'should not find nodes on top outside the viewport when false' do\n      expect(@session.all(:link, 'Download Me', obscured: false).size).to eq(0)\n      @session.scroll_to(@session.find_link('Download Me'))\n      expect(@session.all(:link, 'Download Me', obscured: false).size).to eq(1)\n    end\n\n    it 'should find top nodes outside the viewport when true' do\n      expect(@session.all(:link, 'Download Me', obscured: true).size).to eq(1)\n      @session.scroll_to(@session.find_link('Download Me'))\n      expect(@session.all(:link, 'Download Me', obscured: true).size).to eq(0)\n    end\n\n    it 'should only find non-top nodes when true' do\n      # Also need visible: false so visibility is ignored\n      expect(@session.all(:css, 'a.simple', visible: false, obscured: true).size).to eq(1)\n    end\n  end\n\n  context 'with element count filters' do\n    context ':count' do\n      it 'should succeed when the number of elements founds matches the expectation' do\n        expect { @session.all(:css, 'h1, p', count: 4) }.not_to raise_error\n      end\n\n      it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do\n        expect { @session.all(:css, 'h1, p', count: 5) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n    end\n\n    context ':minimum' do\n      it 'should succeed when the number of elements founds matches the expectation' do\n        expect { @session.all(:css, 'h1, p', minimum: 0) }.not_to raise_error\n      end\n\n      it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do\n        expect { @session.all(:css, 'h1, p', minimum: 5) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n    end\n\n    context ':maximum' do\n      it 'should succeed when the number of elements founds matches the expectation' do\n        expect { @session.all(:css, 'h1, p', maximum: 4) }.not_to raise_error\n      end\n\n      it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do\n        expect { @session.all(:css, 'h1, p', maximum: 0) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n    end\n\n    context ':between' do\n      it 'should succeed when the number of elements founds matches the expectation' do\n        expect { @session.all(:css, 'h1, p', between: 2..7) }.not_to raise_error\n      end\n\n      it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do\n        expect { @session.all(:css, 'h1, p', between: 0..3) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n\n      it 'treats an endless range as minimum' do\n        expect { @session.all(:css, 'h1, p', between: 2..) }.not_to raise_error\n        expect { @session.all(:css, 'h1, p', between: 5..) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n\n      it 'treats a beginless range as maximum' do\n        expect { @session.all(:css, 'h1, p', between: ..7) }.not_to raise_error\n        expect { @session.all(:css, 'h1, p', between: ..3) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n    end\n\n    context 'with multiple count filters' do\n      it 'ignores other filters when :count is specified' do\n        o = { count: 4,\n              minimum: 5,\n              maximum: 0,\n              between: 0..3 }\n        expect { @session.all(:css, 'h1, p', **o) }.not_to raise_error\n      end\n\n      context 'with no :count expectation' do\n        it 'fails if :minimum is not met' do\n          o = { minimum: 5,\n                maximum: 4,\n                between: 2..7 }\n          expect { @session.all(:css, 'h1, p', **o) }.to raise_error(Capybara::ExpectationNotMet)\n        end\n\n        it 'fails if :maximum is not met' do\n          o = { minimum: 0,\n                maximum: 0,\n                between: 2..7 }\n          expect { @session.all(:css, 'h1, p', **o) }.to raise_error(Capybara::ExpectationNotMet)\n        end\n\n        it 'fails if :between is not met' do\n          o = { minimum: 0,\n                maximum: 4,\n                between: 0..3 }\n          expect { @session.all(:css, 'h1, p', **o) }.to raise_error(Capybara::ExpectationNotMet)\n        end\n\n        it 'succeeds if all combineable expectations are met' do\n          o = { minimum: 0,\n                maximum: 4,\n                between: 2..7 }\n          expect { @session.all(:css, 'h1, p', **o) }.not_to raise_error\n        end\n      end\n    end\n  end\n\n  context 'within a scope' do\n    before do\n      @session.visit('/with_scope')\n    end\n\n    it 'should find any element using the given locator' do\n      @session.within(:xpath, \"//div[@id='for_bar']\") do\n        expect(@session.all('.//li').size).to eq(2)\n      end\n    end\n  end\n\n  it 'should have #find_all as an alias' do\n    expect(Capybara::Node::Finders.instance_method(:all)).to eq Capybara::Node::Finders.instance_method(:find_all)\n    expect(@session.find_all('//p').size).to eq(3)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/ancestor_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#ancestor' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  after do\n    Capybara::Selector.remove(:monkey)\n  end\n\n  it 'should find the ancestor element using the given locator' do\n    el = @session.find(:css, '#first_image')\n    expect(el.ancestor('//p')).to have_text('Lorem ipsum dolor')\n    expect(el.ancestor('//a')[:'aria-label']).to eq('Go to simple')\n  end\n\n  it 'should find the ancestor element using the given locator and options' do\n    el = @session.find(:css, '#child')\n    expect(el.ancestor('//div', text: \"Ancestor\\nAncestor\\nAncestor\")[:id]).to eq('ancestor3')\n  end\n\n  it 'should find the closest ancestor' do\n    el = @session.find(:css, '#child')\n    expect(el.ancestor('.//div', order: :reverse, match: :first)[:id]).to eq('ancestor1')\n  end\n\n  it 'should raise an error if there are multiple matches' do\n    el = @session.find(:css, '#child')\n    expect { el.ancestor('//div') }.to raise_error(Capybara::Ambiguous)\n    expect { el.ancestor('//div', text: 'Ancestor') }.to raise_error(Capybara::Ambiguous)\n  end\n\n  context 'with css selectors' do\n    it 'should find the first element using the given locator' do\n      el = @session.find(:css, '#first_image')\n      expect(el.ancestor(:css, 'p')).to have_text('Lorem ipsum dolor')\n      expect(el.ancestor(:css, 'a')[:'aria-label']).to eq('Go to simple')\n    end\n\n    it 'should support pseudo selectors' do\n      el = @session.find(:css, '#button_img')\n      expect(el.ancestor(:css, 'button:disabled')[:id]).to eq('ancestor_button')\n    end\n  end\n\n  context 'with xpath selectors' do\n    it 'should find the first element using the given locator' do\n      el = @session.find(:css, '#first_image')\n      expect(el.ancestor(:xpath, '//p')).to have_text('Lorem ipsum dolor')\n      expect(el.ancestor(:xpath, '//a')[:'aria-label']).to eq('Go to simple')\n    end\n  end\n\n  context 'with custom selector' do\n    it 'should use the custom selector' do\n      Capybara.add_selector(:level) do\n        xpath { |num| \".//*[@id='ancestor#{num}']\" }\n      end\n      el = @session.find(:css, '#child')\n      expect(el.ancestor(:level, 1)[:id]).to eq 'ancestor1'\n      expect(el.ancestor(:level, 3)[:id]).to eq 'ancestor3'\n    end\n  end\n\n  it 'should raise ElementNotFound with a useful default message if nothing was found' do\n    el = @session.find(:css, '#child')\n    expect do\n      el.ancestor(:xpath, '//div[@id=\"nosuchthing\"]')\n    end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath \"//div[@id=\\\\\"nosuchthing\\\\\"]\" that is an ancestor of visible css \"#child\"')\n  end\n\n  context 'within a scope' do\n    it 'should limit the ancestors to inside the scope' do\n      @session.within(:css, '#ancestor2') do\n        el = @session.find(:css, '#child')\n        expect(el.ancestor(:css, 'div', text: 'Ancestor')[:id]).to eq('ancestor1')\n      end\n    end\n  end\n\n  it 'should raise if selector type is unknown' do\n    el = @session.find(:css, '#child')\n    expect do\n      el.ancestor(:unknown, '//h1')\n    end.to raise_error(ArgumentError)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_all_of_selectors_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_all_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selectors are on the page' do\n    @session.assert_all_of_selectors(:css, 'p a#foo', 'h2#h2one', 'h2#h2two')\n  end\n\n  it 'should be false if any of the given selectors are not on the page' do\n    expect { @session.assert_all_of_selectors(:css, 'p a#foo', 'h2#h2three', 'h2#h2one') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect { @session.assert_all_of_selectors('p a#foo', 'h2#h2three', 'h2#h2one') }.to raise_error(Capybara::ElementNotFound)\n    @session.assert_all_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')\n  end\n\n  it 'should support filter block' do\n    expect { @session.assert_all_of_selectors(:css, 'h2#h2one', 'h2#h2two') { |n| n[:id] == 'h2one' } }.to raise_error(Capybara::ElementNotFound, /custom filter block/)\n  end\n\n  context 'should respect scopes' do\n    it 'when used with `within`' do\n      @session.within \"//p[@id='first']\" do\n        @session.assert_all_of_selectors(\".//a[@id='foo']\")\n        expect { @session.assert_all_of_selectors(\".//a[@id='red']\") }.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n\n    it 'when called on elements' do\n      el = @session.find \"//p[@id='first']\"\n      el.assert_all_of_selectors(\".//a[@id='foo']\")\n      expect { el.assert_all_of_selectors(\".//a[@id='red']\") }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with options' do\n    it 'should apply options to all locators' do\n      @session.assert_all_of_selectors(:field, 'normal', 'additional_newline', type: :textarea)\n      expect { @session.assert_all_of_selectors(:field, 'normal', 'test_field', 'additional_newline', type: :textarea) }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not raise error if all the elements appear before given wait duration' do\n      Capybara.using_wait_time(0.1) do\n        @session.visit('/with_js')\n        @session.click_link('Click me')\n        @session.assert_all_of_selectors(:css, 'a#clickable', 'a#has-been-clicked', '#drag', wait: 1.5)\n      end\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_none_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if any of the given locators are on the page' do\n    expect { @session.assert_none_of_selectors(:xpath, '//p', '//a') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_none_of_selectors(:xpath, '//abbr', '//a') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_none_of_selectors(:css, 'p a#foo') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should be true if none of the given locators are on the page' do\n    @session.assert_none_of_selectors(:xpath, '//abbr', '//td')\n    @session.assert_none_of_selectors(:css, 'p a#doesnotexist', 'abbr')\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    @session.assert_none_of_selectors('p a#doesnotexist', 'abbr')\n    expect { @session.assert_none_of_selectors('abbr', 'p a#foo') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  context 'should respect scopes' do\n    it 'when used with `within`' do\n      @session.within \"//p[@id='first']\" do\n        expect { @session.assert_none_of_selectors(\".//a[@id='foo']\") }.to raise_error(Capybara::ElementNotFound)\n        @session.assert_none_of_selectors(\".//a[@id='red']\")\n      end\n    end\n\n    it 'when called on an element' do\n      el = @session.find \"//p[@id='first']\"\n      expect { el.assert_none_of_selectors(\".//a[@id='foo']\") }.to raise_error(Capybara::ElementNotFound)\n      el.assert_none_of_selectors(\".//a[@id='red']\")\n    end\n  end\n\n  context 'with options' do\n    it 'should apply the options to all locators' do\n      expect { @session.assert_none_of_selectors('//p//a', text: 'Redirect') }.to raise_error(Capybara::ElementNotFound)\n      @session.assert_none_of_selectors('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is matched' do\n      expect { @session.assert_none_of_selectors('//p//a', text: /re[dab]i/i, count: 1) }.to raise_error(Capybara::ElementNotFound)\n      @session.assert_none_of_selectors('//p//a', text: /Red$/)\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not find elements if they appear after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      @session.assert_none_of_selectors(:css, '#new_field', 'a#has-been-clicked', wait: 0.1)\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_any_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if any of the given selectors are on the page' do\n    @session.assert_any_of_selectors(:css, 'a#foo', 'h2#h2three')\n    @session.assert_any_of_selectors(:css, 'h2#h2three', 'a#foo')\n  end\n\n  it 'should be false if none of the given selectors are on the page' do\n    expect { @session.assert_any_of_selectors(:css, 'h2#h2three', 'h4#h4four') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect { @session.assert_any_of_selectors('h2#h2three', 'h5#h5five') }.to raise_error(Capybara::ElementNotFound)\n    @session.assert_any_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')\n  end\n\n  it 'should support filter block' do\n    expect { @session.assert_any_of_selectors(:css, 'h2#h2one', 'h2#h2two') { |_n| false } }.to raise_error(Capybara::ElementNotFound, /custom filter block/)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_current_path_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_current_path' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should not raise if the page has the given current path' do\n    expect { @session.assert_current_path('/with_js') }.not_to raise_error\n  end\n\n  it 'should allow regexp matches' do\n    expect { @session.assert_current_path(/w[a-z]{3}_js/) }.not_to raise_error\n  end\n\n  it 'should wait for current_path', requires: [:js] do\n    @session.click_link('Change page')\n    expect { @session.assert_current_path('/with_html') }.not_to raise_error\n  end\n\n  it 'should raise if the page has not the given current_path' do\n    expect { @session.assert_current_path('/with_html') }.to raise_error(Capybara::ExpectationNotMet, 'expected \"/with_js\" to equal \"/with_html\"')\n  end\n\n  it 'should check query options' do\n    @session.visit('/with_js?test=test')\n    expect { @session.assert_current_path('/with_js?test=test') }.not_to raise_error\n  end\n\n  it 'should compare the full url' do\n    expect { @session.assert_current_path(%r{\\Ahttp://[^/]*/with_js\\Z}, url: true) }.not_to raise_error\n  end\n\n  it 'should ignore the query' do\n    @session.visit('/with_js?test=test')\n    expect { @session.assert_current_path('/with_js', ignore_query: true) }.not_to raise_error\n  end\n\n  it 'should not cause an exception when current_url is nil' do\n    allow(@session).to receive(:current_url).and_return(nil)\n    allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page\n\n    expect { @session.assert_current_path(nil) }.not_to raise_error\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_no_current_path?' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should raise if the page has the given current_path' do\n    expect { @session.assert_no_current_path('/with_js') }.to raise_error(Capybara::ExpectationNotMet)\n  end\n\n  it 'should allow regexp matches' do\n    expect { @session.assert_no_current_path(/monkey/) }.not_to raise_error\n  end\n\n  it 'should wait for current_path to disappear', requires: [:js] do\n    @session.click_link('Change page')\n    expect { @session.assert_no_current_path('/with_js') }.not_to raise_error\n  end\n\n  it 'should not raise if the page has not the given current_path' do\n    expect { @session.assert_no_current_path('/with_html') }.not_to raise_error\n  end\n\n  it 'should not cause an exception when current_url is nil' do\n    allow(@session).to receive(:current_url).and_return(nil)\n    allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page\n\n    expect { @session.assert_no_current_path('/with_html') }.not_to raise_error\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_selector_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_selector' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selector is on the page' do\n    @session.assert_selector(:xpath, '//p')\n    @session.assert_selector(:css, 'p a#foo')\n    @session.assert_selector(\"//p[contains(.,'est')]\")\n  end\n\n  it 'should be false if the given selector is not on the page' do\n    expect { @session.assert_selector(:xpath, '//abbr') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_selector(:css, 'p a#doesnotexist') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_selector(\"//p[contains(.,'thisstringisnotonpage')]\") }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect { @session.assert_selector('p a#doesnotexist') }.to raise_error(Capybara::ElementNotFound)\n    @session.assert_selector('p a#foo')\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      @session.assert_selector(\".//a[@id='foo']\")\n      expect { @session.assert_selector(\".//a[@id='red']\") }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with count' do\n    it 'should be true if the content is on the page the given number of times' do\n      @session.assert_selector('//p', count: 3)\n      @session.assert_selector(\"//p//a[@id='foo']\", count: 1)\n      @session.assert_selector(\"//p[contains(.,'est')]\", count: 1)\n    end\n\n    it 'should be false if the content is on the page the given number of times' do\n      expect { @session.assert_selector('//p', count: 6) }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.assert_selector(\"//p//a[@id='foo']\", count: 2) }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.assert_selector(\"//p[contains(.,'est')]\", count: 5) }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it \"should be false if the content isn't on the page at all\" do\n      expect { @session.assert_selector('//abbr', count: 2) }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.assert_selector(\"//p//a[@id='doesnotexist']\", count: 1) }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      @session.assert_selector('//p//a', text: 'Redirect', count: 1)\n      expect { @session.assert_selector('//p', text: 'Doesnotexist') }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should discard all matches where the given regexp is not matched' do\n      @session.assert_selector('//p//a', text: /re[dab]i/i, count: 1)\n      expect { @session.assert_selector('//p//a', text: /Red$/) }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should find element if it appears before given wait duration' do\n      Capybara.using_wait_time(0.1) do\n        @session.visit('/with_js')\n        @session.click_link('Click me')\n        @session.assert_selector(:css, 'a#has-been-clicked', text: 'Has been clicked', wait: 2)\n      end\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_no_selector' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given selector is on the page' do\n    expect { @session.assert_no_selector(:xpath, '//p') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_no_selector(:css, 'p a#foo') }.to raise_error(Capybara::ElementNotFound)\n    expect { @session.assert_no_selector(\"//p[contains(.,'est')]\") }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should be true if the given selector is not on the page' do\n    @session.assert_no_selector(:xpath, '//abbr')\n    @session.assert_no_selector(:css, 'p a#doesnotexist')\n    @session.assert_no_selector(\"//p[contains(.,'thisstringisnotonpage')]\")\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    @session.assert_no_selector('p a#doesnotexist')\n    expect { @session.assert_no_selector('p a#foo') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect { @session.assert_no_selector(\".//a[@id='foo']\") }.to raise_error(Capybara::ElementNotFound)\n      @session.assert_no_selector(\".//a[@id='red']\")\n    end\n  end\n\n  context 'with count' do\n    it 'should be false if the content is on the page the given number of times' do\n      expect { @session.assert_no_selector('//p', count: 3) }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.assert_no_selector(\"//p//a[@id='foo']\", count: 1) }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.assert_no_selector(\"//p[contains(.,'est')]\", count: 1) }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should be true if the content is on the page the wrong number of times' do\n      @session.assert_no_selector('//p', count: 6)\n      @session.assert_no_selector(\"//p//a[@id='foo']\", count: 2)\n      @session.assert_no_selector(\"//p[contains(.,'est')]\", count: 5)\n    end\n\n    it \"should be true if the content isn't on the page at all\" do\n      @session.assert_no_selector('//abbr', count: 2)\n      @session.assert_no_selector(\"//p//a[@id='doesnotexist']\", count: 1)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is contained' do\n      expect { @session.assert_no_selector('//p//a', text: 'Redirect', count: 1) }.to raise_error(Capybara::ElementNotFound)\n      @session.assert_no_selector('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is matched' do\n      expect { @session.assert_no_selector('//p//a', text: /re[dab]i/i, count: 1) }.to raise_error(Capybara::ElementNotFound)\n      @session.assert_no_selector('//p//a', text: /Red$/)\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not find element if it appears after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      @session.assert_no_selector(:css, 'a#has-been-clicked', text: 'Has been clicked', wait: 0.1)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_style_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_matches_style', requires: [:css] do\n  it 'should not raise if the elements style contains the given properties' do\n    @session.visit('/with_html')\n    expect do\n      @session.find(:css, '#first').assert_matches_style(display: 'block')\n    end.not_to raise_error\n  end\n\n  it \"should raise error if the elements style doesn't contain the given properties\" do\n    @session.visit('/with_html')\n    expect do\n      @session.find(:css, '#first').assert_matches_style(display: 'inline')\n    end.to raise_error(Capybara::ExpectationNotMet, 'Expected node to have styles {\"display\"=>\"inline\"}. Actual styles were {\"display\"=>\"block\"}')\n  end\n\n  it 'should wait for style', requires: %i[css js] do\n    @session.visit('/with_js')\n    el = @session.find(:css, '#change')\n    @session.click_link('Change size')\n    expect do\n      el.assert_matches_style({ 'font-size': '50px' }, wait: 3)\n    end.not_to raise_error\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_text_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_text' do\n  it 'should be true if the given text is on the page' do\n    @session.visit('/with_html')\n    expect(@session.assert_text('est')).to be(true)\n    expect(@session.assert_text('Lorem')).to be(true)\n    expect(@session.assert_text('Redirect')).to be(true)\n    expect(@session.assert_text(:Redirect)).to be(true)\n    expect(@session.assert_text('text with   whitespace')).to be(true)\n  end\n\n  it 'should support collapsing whitespace' do\n    @session.visit('/with_html')\n    expect(@session.assert_text('text with whitespace', normalize_ws: true)).to be(true)\n  end\n\n  context 'with enabled default collapsing whitespace' do\n    before { Capybara.default_normalize_ws = true }\n\n    it 'should be true if the given unnormalized text is on the page' do\n      @session.visit('/with_html')\n      expect(@session.assert_text('text with   whitespace', normalize_ws: false)).to be(true)\n    end\n\n    it 'should support collapsing whitespace' do\n      @session.visit('/with_html')\n      expect(@session.assert_text('text with whitespace')).to be(true)\n    end\n  end\n\n  it 'should take scopes into account' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session.assert_text('labore')).to be(true)\n    end\n  end\n\n  it 'should raise if scoped to an element which does not have the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect do\n        @session.assert_text('monkey')\n      end.to raise_error(Capybara::ExpectationNotMet, 'expected to find text \"monkey\" in \"labore\"')\n    end\n  end\n\n  it 'should be true if :all given and text is invisible.' do\n    @session.visit('/with_html')\n    expect(@session.assert_text(:all, 'Some of this text is hidden!')).to be(true)\n  end\n\n  it 'should be true if `Capybara.ignore_hidden_elements = true` and text is invisible.' do\n    Capybara.ignore_hidden_elements = false\n    @session.visit('/with_html')\n    expect(@session.assert_text('Some of this text is hidden!')).to be(true)\n  end\n\n  it 'should raise error with a helpful message if the requested text is present but invisible' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#hidden-text')\n    expect do\n      el.assert_text(:visible, 'Some of this text is hidden!')\n    end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time including non-visible text/)\n  end\n\n  it 'should raise error with a helpful message if the requested text is present but with incorrect case' do\n    @session.visit('/with_html')\n    expect do\n      @session.assert_text('Text With   Whitespace')\n    end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time using a case insensitive search/)\n  end\n\n  it 'should raise error with helpful message if requested text is present but invisible and with incorrect case', requires: [:js] do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#uppercase')\n    expect do\n      el.assert_text('text here')\n    end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time using a case insensitive search and it was found 1 time including non-visible text/)\n  end\n\n  it 'should raise the correct error if requested text is missing but contains regex special characters' do\n    @session.visit('/with_html')\n    expect do\n      @session.assert_text('[]*.')\n    end.to raise_error(Capybara::ExpectationNotMet, /expected to find text \"\\[\\]\\*\\.\"/)\n  end\n\n  it 'should be true if the text in the page matches given regexp' do\n    @session.visit('/with_html')\n    expect(@session.assert_text(/Lorem/)).to be(true)\n  end\n\n  it \"should raise error if the text in the page doesn't match given regexp\" do\n    @session.visit('/with_html')\n    expect do\n      @session.assert_text(/xxxxyzzz/)\n    end.to raise_error(Capybara::ExpectationNotMet, %r{\\Aexpected to find text matching /xxxxyzzz/ in \"This is a test\\\\nHeader Class(.+)\"\\Z})\n  end\n\n  it 'should escape any characters that would have special meaning in a regexp' do\n    @session.visit('/with_html')\n    expect do\n      @session.assert_text('.orem')\n    end.to raise_error(Capybara::ExpectationNotMet)\n  end\n\n  it 'should wait for text to appear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session.assert_text('Has been clicked')).to be(true)\n  end\n\n  context 'with between' do\n    it 'should be true if the text occurs within the range given' do\n      @session.visit('/with_count')\n      expect(@session.assert_text('count', between: 1..3)).to be(true)\n    end\n\n    it 'should be false if the text occurs more or fewer times than range' do\n      @session.visit('/with_html')\n      expect do\n        @session.find(:css, '.number').assert_text(/\\d/, between: 0..1)\n      end.to raise_error(Capybara::ExpectationNotMet, 'expected to find text matching /\\\\d/ between 0 and 1 times but found 2 times in \"42\"')\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should find element if it appears before given wait duration' do\n      Capybara.using_wait_time(0) do\n        @session.visit('/with_js')\n        @session.find(:css, '#reload-list').click\n        @session.find(:css, '#the-list').assert_text(\"Foo\\nBar\", wait: 0.9)\n      end\n    end\n\n    it 'should raise error if it appears after given wait duration' do\n      Capybara.using_wait_time(0) do\n        @session.visit('/with_js')\n        @session.find(:css, '#reload-list').click\n        el = @session.find(:css, '#the-list', visible: false)\n        expect do\n          el.assert_text(:all, 'Foo Bar', wait: 0.3)\n        end.to raise_error(Capybara::ExpectationNotMet)\n      end\n    end\n  end\n\n  context 'with multiple count filters' do\n    before do\n      @session.visit('/with_html')\n    end\n\n    it 'ignores other filters when :count is specified' do\n      o = { count: 5,\n            minimum: 6,\n            maximum: 0,\n            between: 0..4 }\n      expect { @session.assert_text('Header', **o) }.not_to raise_error\n    end\n\n    context 'with no :count expectation' do\n      it 'fails if :minimum is not met' do\n        o = { minimum: 6,\n              maximum: 5,\n              between: 2..7 }\n        expect { @session.assert_text('Header', **o) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n\n      it 'fails if :maximum is not met' do\n        o = { minimum: 0,\n              maximum: 0,\n              between: 2..7 }\n        expect { @session.assert_text('Header', **o) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n\n      it 'fails if :between is not met' do\n        o = { minimum: 0,\n              maximum: 5,\n              between: 0..4 }\n        expect { @session.assert_text('Header', **o) }.to raise_error(Capybara::ExpectationNotMet)\n      end\n\n      it 'succeeds if all combineable expectations are met' do\n        o = { minimum: 0,\n              maximum: 5,\n              between: 2..7 }\n        expect { @session.assert_text('Header', **o) }.not_to raise_error\n      end\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_no_text' do\n  it 'should raise error if the given text is on the page at least once' do\n    @session.visit('/with_html')\n    expect do\n      @session.assert_no_text('Lorem')\n    end.to raise_error(Capybara::ExpectationNotMet, /\\Aexpected not to find text \"Lorem\" in \"This is a test.*\"\\z/)\n  end\n\n  it 'should be true if scoped to an element which does not have the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session.assert_no_text('monkey')).to be(true)\n    end\n  end\n\n  it 'should be true if the given text is on the page but not visible' do\n    @session.visit('/with_html')\n    expect(@session.assert_no_text('Inside element with hidden ancestor')).to be(true)\n  end\n\n  it 'should raise error if :all given and text is invisible.' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#hidden-text', visible: false)\n    expect do\n      el.assert_no_text(:all, 'Some of this text is hidden!')\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected not to find text \"Some of this text is hidden!\" in \"Some of this text is hidden!\"')\n  end\n\n  it 'should raise error if :all given and text is invisible.' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#some-hidden-text', visible: false)\n    expect do\n      el.assert_no_text(:visible, 'hidden')\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected not to find text \"hidden\" in \"Some of this text is not hidden\"')\n  end\n\n  it \"should be true if the text in the page doesn't match given regexp\" do\n    @session.visit('/with_html')\n    @session.assert_no_text(/xxxxyzzz/)\n  end\n\n  context 'with count' do\n    it 'should be true if the text occurs within the range given' do\n      @session.visit('/with_count')\n      expect(@session.assert_text('count', count: 2)).to be(true)\n    end\n\n    it 'should be false if the text occurs more or fewer times than range' do\n      @session.visit('/with_html')\n      expect do\n        @session.find(:css, '.number').assert_text(/\\d/, count: 1)\n      end.to raise_error(Capybara::ExpectationNotMet, 'expected to find text matching /\\\\d/ 1 time but found 2 times in \"42\"')\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not find element if it appears after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      @session.find(:css, '#reload-list').click\n      @session.find(:css, '#the-list').assert_no_text('Foo Bar', wait: 0.3)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/assert_title_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_title' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it \"should not raise if the page's title contains the given string\" do\n    expect do\n      @session.assert_title('js')\n    end.not_to raise_error\n  end\n\n  it 'should not raise when given an empty string' do\n    expect do\n      @session.assert_title('')\n    end.not_to raise_error\n  end\n\n  it 'should allow regexp matches' do\n    expect do\n      @session.assert_title(/w[a-z]{3}_js/)\n    end.not_to raise_error\n\n    expect do\n      @session.assert_title(/w[a-z]{10}_js/)\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected \"with_js\" to match /w[a-z]{10}_js/')\n  end\n\n  it 'should wait for title', requires: [:js] do\n    @session.click_link('Change title')\n    expect do\n      @session.assert_title('changed title', wait: 3)\n    end.not_to raise_error\n  end\n\n  it \"should raise error if the title doesn't contain the given string\" do\n    expect do\n      @session.assert_title('monkey')\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected \"with_js\" to include \"monkey\"')\n  end\n\n  it 'should not normalize given title' do\n    @session.visit('/with_js')\n    expect { @session.assert_title('  with_js  ') }.to raise_error(Capybara::ExpectationNotMet)\n  end\n\n  it 'should match correctly normalized title' do\n    uri = Addressable::URI.parse('/with_title')\n    uri.query_values = { title: ' &nbsp; with space &nbsp;title   ' }\n    @session.visit(uri.to_s)\n    @session.assert_title('  with space  title')\n    expect { @session.assert_title('with space title') }.to raise_error(Capybara::ExpectationNotMet)\n  end\n\n  it 'should not normalize given title in error message' do\n    expect do\n      @session.assert_title(2)\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected \"with_js\" to include \"2\"')\n  end\nend\n\nCapybara::SpecHelper.spec '#assert_no_title' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should raise error if the title contains the given string' do\n    expect do\n      @session.assert_no_title('with_j')\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected \"with_js\" not to include \"with_j\"')\n  end\n\n  it 'should allow regexp matches' do\n    expect do\n      @session.assert_no_title(/w[a-z]{3}_js/)\n    end.to raise_error(Capybara::ExpectationNotMet, 'expected \"with_js\" not to match /w[a-z]{3}_js/')\n    @session.assert_no_title(/monkey/)\n  end\n\n  it 'should wait for title to disappear', requires: [:js] do\n    @session.click_link('Change title')\n    expect do\n      @session.assert_no_title('with_js', wait: 3)\n    end.not_to raise_error\n  end\n\n  it \"should not raise if the title doesn't contain the given string\" do\n    expect do\n      @session.assert_no_title('monkey')\n    end.not_to raise_error\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/attach_file_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#attach_file' do\n  let(:test_file_path) { File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__)) }\n  let(:another_test_file_path) { File.expand_path('../fixtures/another_test_file.txt', File.dirname(__FILE__)) }\n  let(:test_jpg_file_path) { File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__)) }\n  let(:no_extension_file_path) { File.expand_path('../fixtures/no_extension', File.dirname(__FILE__)) }\n\n  before do\n    @session.visit('/form')\n  end\n\n  context 'with normal form' do\n    it 'should set a file path by id' do\n      @session.attach_file 'form_image', with_os_path_separators(__FILE__)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'should set a file path by label' do\n      @session.attach_file 'Image', with_os_path_separators(__FILE__)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'should be able to set on element if no locator passed' do\n      ff = @session.find(:file_field, 'Image')\n      ff.attach_file(with_os_path_separators(__FILE__))\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'casts to string' do\n      @session.attach_file :form_image, with_os_path_separators(__FILE__)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n  end\n\n  context 'with multipart form' do\n    it 'should set a file path by id' do\n      @session.attach_file 'form_document', with_os_path_separators(test_file_path)\n      @session.click_button('Upload Single')\n      expect(@session).to have_content(File.read(test_file_path))\n    end\n\n    it 'should set a file path by label' do\n      @session.attach_file 'Single Document', with_os_path_separators(test_file_path)\n      @session.click_button('Upload Single')\n      expect(@session).to have_content(File.read(test_file_path))\n    end\n\n    it 'should not break if no file is submitted' do\n      @session.click_button('Upload Single')\n      expect(@session).to have_content('No file uploaded')\n    end\n\n    it 'should send prior hidden field if no file submitted' do\n      @session.click_button('Upload Empty With Hidden')\n      expect(extract_results(@session)['document2']).to eq('hidden_field')\n      expect(extract_content_type(@session)).to start_with('multipart/form-data;')\n    end\n\n    it 'should send content type text/plain when uploading a text file' do\n      @session.attach_file 'Single Document', with_os_path_separators(test_file_path)\n      @session.click_button 'Upload Single'\n      expect(@session).to have_content('text/plain')\n    end\n\n    it 'should send content type image/jpeg when uploading an image' do\n      @session.attach_file 'Single Document', with_os_path_separators(test_jpg_file_path)\n      @session.click_button 'Upload Single'\n      expect(@session).to have_content('image/jpeg')\n    end\n\n    it 'should not break when uploading a file without extension' do\n      @session.attach_file 'Single Document', with_os_path_separators(no_extension_file_path)\n      @session.click_button 'Upload Single'\n      expect(@session).to have_content(File.read(no_extension_file_path))\n    end\n\n    it 'should not break when using HTML5 multiple file input' do\n      @session.attach_file 'Multiple Documents', with_os_path_separators(test_file_path)\n      @session.click_button('Upload Multiple')\n      expect(@session).to have_content(File.read(test_file_path))\n      expect(@session.body).to include('1 | ') # number of files\n    end\n\n    it 'should not break when using HTML5 multiple file input uploading multiple files' do\n      @session.attach_file('Multiple Documents',\n                           [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })\n      @session.click_button('Upload Multiple')\n      expect(@session).to have_content('2 | ') # number of files\n      expect(@session.body).to include(File.read(test_file_path))\n      expect(@session.body).to include(File.read(another_test_file_path))\n    end\n\n    it 'should not send anything when attaching no files to a multiple upload field' do\n      @session.click_button('Upload Empty Multiple')\n      expect(@session).to have_content('Successfully ignored empty file field')\n    end\n\n    it 'should not append files to already attached' do\n      @session.attach_file 'Multiple Documents', with_os_path_separators(test_file_path)\n      @session.attach_file 'Multiple Documents', with_os_path_separators(another_test_file_path)\n      @session.click_button('Upload Multiple')\n      expect(@session).to have_content('1 | ') # number of files\n      expect(@session.body).to include(File.read(another_test_file_path))\n      expect(@session.body).not_to include(File.read(test_file_path))\n    end\n\n    it 'should fire change once when uploading multiple files from empty', requires: [:js] do\n      @session.visit('with_js')\n      @session.attach_file('multiple-file',\n                           [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })\n      expect(@session).to have_css('.file_change', count: 1)\n    end\n\n    it 'should fire change once for each set of files uploaded', requires: [:js] do\n      @session.visit('with_js')\n      @session.attach_file('multiple-file', [test_jpg_file_path].map { |f| with_os_path_separators(f) })\n      @session.attach_file('multiple-file',\n                           [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })\n      expect(@session).to have_css('.file_change', count: 2)\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find file field \"does not exist\"/\n      expect do\n        @session.attach_file('does not exist', with_os_path_separators(test_file_path))\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context \"with a path that doesn't exist\" do\n    it 'should raise an error' do\n      expect { @session.attach_file('Image', '/no_such_file.png') }.to raise_error(Capybara::FileNotFound)\n    end\n  end\n\n  context 'with :exact option' do\n    it 'should set a file path by partial label when false' do\n      @session.attach_file 'Imag', with_os_path_separators(__FILE__), exact: false\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'should not allow partial matches when true' do\n      expect do\n        @session.attach_file 'Imag', with_os_path_separators(__FILE__), exact: true\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with :make_visible option', requires: %i[js es_args] do\n    it 'applies a default style change when true' do\n      @session.visit('/with_js')\n      expect do\n        @session.attach_file('hidden_file', with_os_path_separators(__FILE__))\n      end.to raise_error Capybara::ElementNotFound\n      expect do\n        @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)\n      end.not_to raise_error\n    end\n\n    it 'accepts a hash of styles to be applied' do\n      @session.visit('/with_js')\n      expect do\n        @session.attach_file('hidden_file',\n                             with_os_path_separators(__FILE__),\n                             make_visible: { opacity: 1, display: 'block' })\n      end.not_to raise_error\n    end\n\n    it 'raises an error when the file input is not made visible' do\n      @session.visit('/with_js')\n      expect do\n        @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: { color: 'red' })\n      end.to raise_error(Capybara::ExpectationNotMet)\n    end\n\n    it 'resets the style when done' do\n      @session.visit('/with_js')\n      @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)\n      expect(@session.evaluate_script('arguments[0].style.display', @session.find(:css, '#hidden_file', visible: :all))).to eq 'none'\n    end\n\n    it 'should fire change' do\n      @session.visit('/with_js')\n      @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)\n      expect(@session).to have_css('.file_change')\n    end\n  end\n\n  context 'with a block', requires: %i[js] do\n    it 'can upload by clicking the file input' do\n      @session.attach_file(with_os_path_separators(__FILE__)) do\n        @session.find(:file_field, 'form[image]').click\n      end\n      @session.click_button('awesome')\n      expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'can upload by clicking the label' do\n      @session.attach_file(with_os_path_separators(__FILE__)) do\n        @session.find(:label, 'Hidden Image').click\n      end\n      @session.click_button('awesome')\n      expect(extract_results(@session)['hidden_image']).to end_with(File.basename(__FILE__))\n    end\n\n    it 'should fire change' do\n      @session.visit('/with_js')\n      @session.attach_file(with_os_path_separators(__FILE__)) do\n        @session.find(:label, 'Label for hidden file input').click\n      end\n      expect(@session).to have_css('.file_change')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/body_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#body' do\n  it 'should return the unmodified page body' do\n    @session.visit('/')\n    expect(@session).to have_content('Hello world!') # wait for content to appear if visit is async\n    expect(@session.body).to include('Hello world!')\n  end\n\n  context 'encoding of response between ascii and utf8' do\n    it 'should be valid with html entities' do\n      @session.visit('/with_html_entities')\n      expect(@session).to have_content('Encoding') # wait for content to appear if visit is async\n      expect { @session.body.encode!('UTF-8') }.not_to raise_error\n    end\n\n    it 'should be valid without html entities' do\n      @session.visit('/with_html')\n      expect(@session).to have_content('This is a test') # wait for content to appear if visit is async\n      expect { @session.body.encode!('UTF-8') }.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/check_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#check' do\n  before do\n    @session.visit('/form')\n  end\n\n  describe \"'checked' attribute\" do\n    it 'should be true if checked' do\n      @session.check('Terms of Use')\n      expect(@session.find(:xpath, \"//input[@id='form_terms_of_use']\")['checked']).to be_truthy\n    end\n\n    it 'should be false if unchecked' do\n      expect(@session.find(:xpath, \"//input[@id='form_terms_of_use']\")['checked']).to be_falsey\n    end\n  end\n\n  it 'should trigger associated events', requires: [:js] do\n    @session.visit('/with_js')\n    @session.check('checkbox_with_event')\n    expect(@session).to have_css('#checkbox_event_triggered')\n  end\n\n  describe 'checking' do\n    it 'should not change an already checked checkbox' do\n      expect(@session.find(:xpath, \"//input[@id='form_pets_dog']\")).to be_checked\n      @session.check('form_pets_dog')\n      expect(@session.find(:xpath, \"//input[@id='form_pets_dog']\")).to be_checked\n    end\n\n    it 'should check an unchecked checkbox' do\n      expect(@session.find(:xpath, \"//input[@id='form_pets_cat']\")).not_to be_checked\n      @session.check('form_pets_cat')\n      expect(@session.find(:xpath, \"//input[@id='form_pets_cat']\")).to be_checked\n    end\n  end\n\n  describe 'unchecking' do\n    it 'should not change an already unchecked checkbox' do\n      expect(@session.find(:xpath, \"//input[@id='form_pets_cat']\")).not_to be_checked\n      @session.uncheck('form_pets_cat')\n      expect(@session.find(:xpath, \"//input[@id='form_pets_cat']\")).not_to be_checked\n    end\n\n    it 'should uncheck a checked checkbox' do\n      expect(@session.find(:xpath, \"//input[@id='form_pets_dog']\")).to be_checked\n      @session.uncheck('form_pets_dog')\n      expect(@session.find(:xpath, \"//input[@id='form_pets_dog']\")).not_to be_checked\n    end\n  end\n\n  it 'should check a checkbox by id' do\n    @session.check('form_pets_cat')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')\n  end\n\n  it 'should check a checkbox by label' do\n    @session.check('Cat')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')\n  end\n\n  it 'should work without a locator string' do\n    @session.check(id: 'form_pets_cat')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')\n  end\n\n  it 'should be able to check itself if no locator specified' do\n    cb = @session.find(:id, 'form_pets_cat')\n    cb.check\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')\n  end\n\n  it 'casts to string' do\n    @session.check(:form_pets_cat)\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find checkbox \"does not exist\"/\n      expect do\n        @session.check('does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with a disabled checkbox' do\n    it 'should raise an error' do\n      msg = 'Unable to find visible checkbox \"Disabled Checkbox\" that is not disabled'\n      expect do\n        @session.check('Disabled Checkbox')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.check('Ham', exact: false)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['pets']).to include('hamster')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.check('Ham', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with `option` option' do\n    it 'can check boxes by their value' do\n      @session.check('form[pets][]', option: 'cat')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['pets']).to include('cat')\n    end\n\n    it 'should alias `with`' do\n      @session.check('form[pets][]', with: 'cat')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['pets']).to include('cat')\n    end\n\n    it 'should raise an error if option not found' do\n      expect do\n        @session.check('form[pets][]', option: 'elephant')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'when checkbox hidden' do\n    context 'with Capybara.automatic_label_click == true' do\n      around do |spec|\n        old_click_label, Capybara.automatic_label_click = Capybara.automatic_label_click, true\n        spec.run\n        Capybara.automatic_label_click = old_click_label\n      end\n\n      it 'should check via clicking the label with :for attribute if possible' do\n        expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy\n        @session.check('form_cars_tesla')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).to include('tesla')\n      end\n\n      it 'should check via clicking the wrapping label if possible' do\n        expect(@session.find(:checkbox, 'form_cars_mclaren', unchecked: true, visible: :hidden)).to be_truthy\n        @session.check('form_cars_mclaren')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).to include('mclaren')\n      end\n\n      it 'should check via clicking the label with :for attribute if locator nil' do\n        cb = @session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)\n        cb.check\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).to include('tesla')\n      end\n\n      it 'should check self via clicking the wrapping label if locator nil' do\n        cb = @session.find(:checkbox, 'form_cars_mclaren', unchecked: true, visible: :hidden)\n        cb.check\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).to include('mclaren')\n      end\n\n      it 'should not click the label if unneeded' do\n        expect(@session.find(:checkbox, 'form_cars_jaguar', checked: true, visible: :hidden)).to be_truthy\n        @session.check('form_cars_jaguar')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).to include('jaguar')\n      end\n\n      it 'should raise original error when no label available' do\n        expect { @session.check('form_cars_ariel') }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox \"form_cars_ariel\"/)\n      end\n\n      it 'should raise error if not allowed to click label' do\n        expect { @session.check('form_cars_mclaren', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox \"form_cars_mclaren\"/)\n      end\n    end\n\n    context 'with Capybara.automatic_label_click == false' do\n      around do |spec|\n        old_label_click, Capybara.automatic_label_click = Capybara.automatic_label_click, false\n        spec.run\n        Capybara.automatic_label_click = old_label_click\n      end\n\n      it 'should raise error if checkbox not visible' do\n        expect { @session.check('form_cars_mclaren') }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox \"form_cars_mclaren\"/)\n      end\n\n      it 'should include node filter in error if verified' do\n        expect { @session.check('form_cars_maserati') }.to raise_error(Capybara::ElementNotFound, 'Unable to find visible checkbox \"form_cars_maserati\" that is not disabled')\n      end\n\n      context 'with allow_label_click == true' do\n        it 'should check via the label if input is hidden' do\n          expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy\n          @session.check('form_cars_tesla', allow_label_click: true)\n          @session.click_button('awesome')\n          expect(extract_results(@session)['cars']).to include('tesla')\n        end\n\n        it 'should not wait the full time if label can be clicked' do\n          expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy\n          start_time = Time.now\n          @session.check('form_cars_tesla', allow_label_click: true, wait: 10)\n          end_time = Time.now\n          expect(end_time - start_time).to be < 10\n        end\n\n        it 'should check via the label if input is moved off the left edge of the page' do\n          expect(@session.find(:checkbox, 'form_cars_pagani', unchecked: true, visible: :all)).to be_truthy\n          @session.check('form_cars_pagani', allow_label_click: true)\n          @session.click_button('awesome')\n          expect(extract_results(@session)['cars']).to include('pagani')\n        end\n\n        it 'should check via the label if input is visible but blocked by another element' do\n          expect(@session.find(:checkbox, 'form_cars_bugatti', unchecked: true, visible: :all)).to be_truthy\n          @session.check('form_cars_bugatti', allow_label_click: true)\n          @session.click_button('awesome')\n          expect(extract_results(@session)['cars']).to include('bugatti')\n        end\n\n        it 'should check via label if multiple labels' do\n          expect(@session).to have_field('multi_label_checkbox', checked: false, visible: :hidden)\n          @session.check('Label to click', allow_label_click: true)\n          expect(@session).to have_field('multi_label_checkbox', checked: true, visible: :hidden)\n        end\n      end\n\n      context 'with allow_label_click options', requires: [:js] do\n        it 'should allow offsets to click location on label' do\n          Capybara.w3c_click_offset = false\n          expect(@session.find(:checkbox, 'form_cars_lotus', unchecked: true, visible: :hidden)).to be_truthy\n          @session.check('form_cars_lotus', allow_label_click: { x: 90, y: 10 })\n          @session.click_button('awesome')\n          expect(extract_results(@session)['cars']).to include('lotus')\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/choose_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#choose' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should choose a radio button by id' do\n    @session.choose('gender_male')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['gender']).to eq('male')\n  end\n\n  it 'ignores readonly attribute on radio buttons' do\n    @session.choose('gender_both')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['gender']).to eq('both')\n  end\n\n  it 'should choose a radio button by label' do\n    @session.choose('Both')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['gender']).to eq('both')\n  end\n\n  it 'should work without a locator string' do\n    @session.choose(id: 'gender_male')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['gender']).to eq('male')\n  end\n\n  it 'should be able to choose self when no locator string specified' do\n    rb = @session.find(:id, 'gender_male')\n    rb.choose\n    @session.click_button('awesome')\n    expect(extract_results(@session)['gender']).to eq('male')\n  end\n\n  it 'casts to string' do\n    @session.choose('Both')\n    @session.click_button(:awesome)\n    expect(extract_results(@session)['gender']).to eq('both')\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find radio button \"does not exist\"/\n      expect do\n        @session.choose('does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with a disabled radio button' do\n    it 'should raise an error' do\n      expect do\n        @session.choose('Disabled Radio')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.choose('Mal', exact: false)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['gender']).to eq('male')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.choose('Mal', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with `option` option' do\n    it 'can check radio buttons by their value' do\n      @session.choose('form[gender]', option: 'male')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['gender']).to eq('male')\n    end\n\n    it 'should alias `:with` option' do\n      @session.choose('form[gender]', with: 'male')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['gender']).to eq('male')\n    end\n\n    it 'should raise an error if option not found' do\n      expect do\n        @session.choose('form[gender]', option: 'hermaphrodite')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with hidden radio buttons' do\n    context 'with Capybara.automatic_label_click == true' do\n      around do |spec|\n        old_click_label, Capybara.automatic_label_click = Capybara.automatic_label_click, true\n        spec.run\n        Capybara.automatic_label_click = old_click_label\n      end\n\n      it 'should select by clicking the label if available' do\n        @session.choose('party_democrat')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['party']).to eq('democrat')\n      end\n\n      it 'should select self by clicking the label if no locator specified' do\n        cb = @session.find(:id, 'party_democrat', visible: :hidden)\n        cb.choose\n        @session.click_button('awesome')\n        expect(extract_results(@session)['party']).to eq('democrat')\n      end\n\n      it 'should raise error if not allowed to click label' do\n        expect { @session.choose('party_democrat', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, /Unable to find visible radio button \"party_democrat\"/)\n      end\n    end\n  end\n\n  it 'should return the chosen radio button' do\n    el = @session.find(:radio_button, 'gender_male')\n    expect(@session.choose('gender_male')).to eq el\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/click_button_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#click_button' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should wait for asynchronous load', requires: [:js] do\n    @session.visit('/with_js')\n    @session.using_wait_time(1.5) do\n      @session.click_link('Click me')\n      @session.click_button('New Here')\n    end\n  end\n\n  it 'casts to string' do\n    @session.click_button(:'Relative Action')\n    expect(extract_results(@session)['relative']).to eq('Relative Action')\n    expect(@session.current_path).to eq('/relative')\n  end\n\n  context 'with multiple values with the same name' do\n    it 'should use the latest given value' do\n      @session.check('Terms of Use')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['terms_of_use']).to eq('1')\n    end\n  end\n\n  context 'with a form that has a relative url as an action' do\n    it 'should post to the correct url' do\n      @session.click_button('Relative Action')\n      expect(extract_results(@session)['relative']).to eq('Relative Action')\n      expect(@session.current_path).to eq('/relative')\n    end\n  end\n\n  context 'with a form that has no action specified' do\n    it 'should post to the correct url' do\n      @session.click_button('No Action')\n      expect(extract_results(@session)['no_action']).to eq('No Action')\n      expect(@session.current_path).to eq('/form')\n    end\n  end\n\n  context 'with value given on a submit button' do\n    context 'on a form with HTML5 fields' do\n      let(:results) { extract_results(@session) }\n\n      before do\n        @session.click_button('html5_submit')\n      end\n\n      it 'should serialise and submit search fields' do\n        expect(results['html5_search']).to eq('what are you looking for')\n      end\n\n      it 'should serialise and submit email fields' do\n        expect(results['html5_email']).to eq('person@email.com')\n      end\n\n      it 'should serialise and submit url fields' do\n        expect(results['html5_url']).to eq('http://www.example.com')\n      end\n\n      it 'should serialise and submit tel fields' do\n        expect(results['html5_tel']).to eq('911')\n      end\n\n      it 'should serialise and submit color fields' do\n        expect(results['html5_color'].upcase).to eq('#FFFFFF')\n      end\n    end\n\n    context 'on an HTML4 form' do\n      let(:results) { extract_results(@session) }\n\n      before do\n        @session.click_button('awesome')\n      end\n\n      it 'should serialize and submit text fields' do\n        expect(results['first_name']).to eq('John')\n      end\n\n      it 'should escape fields when submitting' do\n        expect(results['phone']).to eq('+1 555 7021')\n      end\n\n      it 'should serialize and submit password fields' do\n        expect(results['password']).to eq('seeekrit')\n      end\n\n      it 'should serialize and submit hidden fields' do\n        expect(results['token']).to eq('12345')\n      end\n\n      it 'should not serialize fields from other forms' do\n        expect(results['middle_name']).to be_nil\n      end\n\n      it 'should submit the button that was clicked, but not other buttons' do\n        expect(results['awesome']).to eq('awesome')\n        expect(results['crappy']).to be_nil\n      end\n\n      it 'should serialize radio buttons' do\n        expect(results['gender']).to eq('female')\n      end\n\n      it \"should default radio value to 'on' if none specified\" do\n        expect(results['valueless_radio']).to eq('on')\n      end\n\n      it 'should serialize check boxes' do\n        expect(results['pets']).to include('dog', 'hamster')\n        expect(results['pets']).not_to include('cat')\n      end\n\n      it \"should default checkbox value to 'on' if none specififed\" do\n        expect(results['valueless_checkbox']).to eq('on')\n      end\n\n      it 'should serialize text areas' do\n        expect(results['description']).to eq('Descriptive text goes here')\n      end\n\n      it 'should serialize select tag with values' do\n        expect(results['locale']).to eq('en')\n      end\n\n      it 'should serialize select tag without values' do\n        expect(results['region']).to eq('Norway')\n      end\n\n      it 'should serialize first option for select tag with no selection' do\n        expect(results['city']).to eq('London')\n      end\n\n      it 'should not serialize a select tag without options' do\n        expect(results['tendency']).to be_nil\n      end\n\n      it 'should convert lf to cr/lf in submitted textareas' do\n        expect(results['newline']).to eq(\"\\r\\nNew line after and before textarea tag\\r\\n\")\n      end\n\n      it 'should not submit disabled fields' do\n        expect(results['disabled_text_field']).to be_nil\n        expect(results['disabled_textarea']).to be_nil\n        expect(results['disabled_checkbox']).to be_nil\n        expect(results['disabled_radio']).to be_nil\n        expect(results['disabled_select']).to be_nil\n        expect(results['disabled_file']).to be_nil\n      end\n    end\n  end\n\n  context 'input type=submit button' do\n    it 'should submit by button id' do\n      @session.click_button('awe123')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by specific button id' do\n      @session.click_button(id: 'awe123')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by button title' do\n      @session.click_button('What an Awesome Button')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by partial title', :exact_false do\n      @session.click_button('What an Awesome')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by button name' do\n      @session.click_button('form[awesome]')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by specific button name' do\n      @session.click_button(name: 'form[awesome]')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit by specific button name regex' do\n      @session.click_button(name: /form\\[awes.*\\]/)\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'when Capybara.enable_aria_role = true' do\n    it 'should click on a button role', requires: [:js] do\n      Capybara.enable_aria_role = true\n      @session.using_wait_time(1.5) do\n        @session.visit('/with_js')\n        @session.click_button('ARIA button')\n        expect(@session).to have_button('ARIA button has been clicked')\n      end\n    end\n  end\n\n  context 'with fields associated with the form using the form attribute', requires: [:form_attribute] do\n    let(:results) { extract_results(@session) }\n\n    before do\n      @session.click_button('submit_form1')\n    end\n\n    it 'should serialize and submit text fields' do\n      expect(results['outside_input']).to eq('outside_input')\n    end\n\n    it 'should serialize text areas' do\n      expect(results['outside_textarea']).to eq('Some text here')\n    end\n\n    it 'should serialize select tags' do\n      expect(results['outside_select']).to eq('Ruby')\n    end\n\n    it 'should not serliaze fields associated with a different form' do\n      expect(results['for_form2']).to be_nil\n    end\n  end\n\n  context 'with submit button outside the form defined by <button> tag', requires: [:form_attribute] do\n    let(:results) { extract_results(@session) }\n\n    before do\n      @session.click_button('outside_button')\n    end\n\n    it 'should submit the associated form' do\n      expect(results['which_form']).to eq('form2')\n    end\n\n    it 'should submit the button that was clicked, but not other buttons' do\n      expect(results['outside_button']).to eq('outside_button')\n      expect(results['unused']).to be_nil\n    end\n  end\n\n  context \"with submit button outside the form defined by <input type='submit'> tag\", requires: [:form_attribute] do\n    let(:results) { extract_results(@session) }\n\n    before do\n      @session.click_button('outside_submit')\n    end\n\n    it 'should submit the associated form' do\n      expect(results['which_form']).to eq('form1')\n    end\n\n    it 'should submit the button that was clicked, but not other buttons' do\n      expect(results['outside_submit']).to eq('outside_submit')\n      expect(results['submit_form1']).to be_nil\n    end\n  end\n\n  context 'with submit button for form1 located within form2', requires: [:form_attribute] do\n    it 'should submit the form associated with the button' do\n      @session.click_button('other_form_button')\n      expect(extract_results(@session)['which_form']).to eq('form1')\n    end\n  end\n\n  context 'with submit button not associated with any form' do\n    it 'should not error when clicked' do\n      expect { @session.click_button('no_form_button') }.not_to raise_error\n    end\n  end\n\n  context 'with alt given on an image button' do\n    it 'should submit the associated form' do\n      @session.click_button('oh hai thar')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('hai')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with value given on an image button' do\n    it 'should submit the associated form' do\n      @session.click_button('okay')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('kay')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with id given on an image button' do\n    it 'should submit the associated form' do\n      @session.click_button('okay556')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with title given on an image button' do\n    it 'should submit the associated form' do\n      @session.click_button('Okay 556 Image')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('Okay 556')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with text given on a button defined by <button> tag' do\n    it 'should submit the associated form' do\n      @session.click_button('Click me!')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('Click')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with id given on a button defined by <button> tag' do\n    it 'should submit the associated form' do\n      @session.click_button('click_me_123')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should serialize and send GET forms' do\n      @session.visit('/form')\n      @session.click_button('med')\n      results = extract_results(@session)\n      expect(results['middle_name']).to eq('Darren')\n      expect(results['foo']).to be_nil\n    end\n  end\n\n  context 'with name given on a button defined by <button> tag' do\n    it 'should submit the associated form when name is locator' do\n      @session.click_button('form[no_value]')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should submit the associated form when name is specific' do\n      @session.click_button(name: 'form[no_value]')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with value given on a button defined by <button> tag' do\n    it 'should submit the associated form' do\n      @session.click_button('click_me')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('ck_me')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with title given on a button defined by <button> tag' do\n    it 'should submit the associated form' do\n      @session.click_button('Click Title button')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('Click Title')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with descendant image alt given on a button defined by <button> tag' do\n    it 'should submit the associated form' do\n      @session.click_button('A horse eating hay')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should work with partial matches', :exact_false do\n      @session.click_button('se eating h')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find button \"does not exist\"/\n      expect do\n        @session.click_button('does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with formaction attribute on button' do\n    it 'should submit to the formaction attribute' do\n      @session.click_button('Formaction button')\n      results = extract_results(@session)\n      expect(@session.current_path).to eq '/form'\n      expect(results['which_form']).to eq 'formaction form'\n    end\n  end\n\n  context 'with formmethod attribute on button' do\n    it 'should submit to the formethod attribute' do\n      @session.click_button('Formmethod button')\n      results = extract_results(@session)\n      expect(@session.current_path).to eq '/form/get'\n      expect(results['which_form']).to eq 'formaction form'\n    end\n  end\n\n  it 'should serialize and send valueless buttons that were clicked' do\n    @session.click_button('No Value!')\n    results = extract_results(@session)\n    expect(results['no_value']).not_to be_nil\n  end\n\n  it 'should send button in document order' do\n    @session.click_button('outside_button')\n    results = extract_results(@session)\n    expect(results.keys).to eq %w[for_form2 outside_button which_form post_count]\n  end\n\n  it 'should not send image buttons that were not clicked' do\n    @session.click_button('Click me!')\n    results = extract_results(@session)\n    expect(results['okay']).to be_nil\n  end\n\n  it 'should serialize and send GET forms' do\n    @session.visit('/form')\n    @session.click_button('med')\n    results = extract_results(@session)\n    expect(results['middle_name']).to eq('Darren')\n    expect(results['foo']).to be_nil\n  end\n\n  it 'should follow redirects' do\n    @session.click_button('Go FAR')\n    expect(@session).to have_content('You landed')\n    expect(@session.current_url).to match(%r{/landed$})\n  end\n\n  it 'should follow temporary redirects that maintain method' do\n    @session.click_button('Go 307')\n    expect(@session).to have_content('You post landed: TWTW')\n  end\n\n  it 'should follow permanent redirects that maintain method' do\n    @session.click_button('Go 308')\n    expect(@session).to have_content('You post landed: TWTW')\n  end\n\n  it 'should post pack to the same URL when no action given' do\n    @session.visit('/postback')\n    @session.click_button('With no action')\n    expect(@session).to have_content('Postback')\n  end\n\n  it 'should post pack to the same URL when blank action given' do\n    @session.visit('/postback')\n    @session.click_button('With blank action')\n    expect(@session).to have_content('Postback')\n  end\n\n  it 'ignores disabled buttons' do\n    expect do\n      @session.click_button('Disabled button')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should encode complex field names, like array[][value]' do\n    @session.visit('/form')\n    @session.fill_in('address1_city', with: 'Paris')\n    @session.fill_in('address1_street', with: 'CDG')\n\n    @session.fill_in('address2_city', with: 'Mikolaiv')\n    @session.fill_in('address2_street', with: 'PGS')\n\n    @session.click_button 'awesome'\n\n    addresses = extract_results(@session)['addresses']\n    expect(addresses.size).to eq(2)\n\n    expect(addresses[0]['street']).to eq('CDG')\n    expect(addresses[0]['city']).to eq('Paris')\n    expect(addresses[0]['country']).to eq('France')\n\n    expect(addresses[1]['street']).to eq('PGS')\n    expect(addresses[1]['city']).to eq('Mikolaiv')\n    expect(addresses[1]['country']).to eq('Ukraine')\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.click_button('What an Awesome', exact: false)\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.click_button('What an Awesome', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  it 'should work with popovers' do\n    @session.click_button('Show popover')\n    clickable = @session.find(:button, 'Should be clickable', visible: false)\n    expect(clickable).to be_visible\n    expect do\n      @session.click_button('Should be clickable')\n    end.not_to raise_error\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/click_link_or_button_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#click_link_or_button' do\n  it 'should click on a link' do\n    @session.visit('/with_html')\n    @session.click_link_or_button('labore')\n    expect(@session).to have_content('Bar')\n  end\n\n  it 'should click on a button' do\n    @session.visit('/form')\n    @session.click_link_or_button('awe123')\n    expect(extract_results(@session)['first_name']).to eq('John')\n  end\n\n  it 'should click on a button with no type attribute' do\n    @session.visit('/form')\n    @session.click_link_or_button('no_type')\n    expect(extract_results(@session)['first_name']).to eq('John')\n  end\n\n  it 'should be aliased as click_on' do\n    @session.visit('/form')\n    @session.click_on('awe123')\n    expect(extract_results(@session)['first_name']).to eq('John')\n  end\n\n  it 'should wait for asynchronous load', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    @session.click_link_or_button('Has been clicked')\n  end\n\n  it 'casts to string' do\n    @session.visit('/form')\n    @session.click_link_or_button(:awe123)\n    expect(extract_results(@session)['first_name']).to eq('John')\n  end\n\n  context 'with test_id' do\n    it 'should click on a button' do\n      Capybara.test_id = 'data-test-id'\n      @session.visit('/form')\n      @session.click_link_or_button('test_id_button')\n      expect(extract_results(@session)['first_name']).to eq('John')\n    end\n  end\n\n  context 'with :exact option' do\n    context 'when `false`' do\n      it 'clicks on approximately matching link' do\n        @session.visit('/with_html')\n        @session.click_link_or_button('abore', exact: false)\n        expect(@session).to have_content('Bar')\n      end\n\n      it 'clicks on approximately matching button' do\n        @session.visit('/form')\n        @session.click_link_or_button('awe', exact: false)\n        expect(extract_results(@session)['first_name']).to eq('John')\n      end\n    end\n\n    context 'when `true`' do\n      it 'does not click on link which matches approximately' do\n        @session.visit('/with_html')\n        msg = 'Unable to find link or button \"abore\"'\n        expect do\n          @session.click_link_or_button('abore', exact: true)\n        end.to raise_error(Capybara::ElementNotFound, msg)\n      end\n\n      it 'does not click on approximately matching button' do\n        @session.visit('/form')\n        msg = 'Unable to find link or button \"awe\"'\n\n        expect do\n          @session.click_link_or_button('awe', exact: true)\n        end.to raise_error(Capybara::ElementNotFound, msg)\n      end\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      @session.visit('/with_html')\n      msg = 'Unable to find link or button \"does not exist\"'\n      expect do\n        @session.click_link_or_button('does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with :disabled option' do\n    it 'ignores disabled buttons when false' do\n      @session.visit('/form')\n      expect do\n        @session.click_link_or_button('Disabled button', disabled: false)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'ignores disabled buttons by default' do\n      @session.visit('/form')\n      expect do\n        @session.click_link_or_button('Disabled button')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'happily clicks on links which incorrectly have the disabled attribute' do\n      @session.visit('/with_html')\n      @session.click_link_or_button('Disabled link')\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  it 'should return the element clicked' do\n    @session.visit('/with_html')\n    link = @session.find(:link, 'Blank Anchor')\n    expect(@session.click_link_or_button('Blank Anchor')).to eq link\n  end\n\n  context 'with enable_aria_label' do\n    it 'should click on link' do\n      @session.visit('/with_html')\n      expect do\n        @session.click_link_or_button('Go to simple', enable_aria_label: true)\n      end.not_to raise_error\n    end\n\n    it 'should click on button' do\n      @session.visit('/form')\n      expect do\n        @session.click_link_or_button('Aria button', enable_aria_label: true)\n      end.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/click_link_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#click_link' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should wait for asynchronous load', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    @session.click_link('Has been clicked')\n  end\n\n  it 'casts to string' do\n    @session.click_link(:foo)\n    expect(@session).to have_content('Another World')\n  end\n\n  it 'raises any errors caught inside the server', requires: [:server] do\n    quietly { @session.visit('/error') }\n    expect do\n      @session.click_link('foo')\n    end.to raise_error(TestApp::TestAppError)\n  end\n\n  context 'with id given' do\n    it 'should take user to the linked page' do\n      @session.click_link('foo')\n      expect(@session).to have_content('Another World')\n    end\n  end\n\n  context 'with text given' do\n    it 'should take user to the linked page' do\n      @session.click_link('labore')\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should accept partial matches', :exact_false do\n      @session.click_link('abo')\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with title given' do\n    it 'should take user to the linked page' do\n      @session.click_link('awesome title')\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should accept partial matches', :exact_false do\n      @session.click_link('some titl')\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with alternative text given to a contained image' do\n    it 'should take user to the linked page' do\n      @session.click_link('awesome image')\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should accept partial matches', :exact_false do\n      @session.click_link('some imag')\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = 'Unable to find link \"does not exist\"'\n      expect do\n        @session.click_link('does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with :href option given' do\n    it 'should find links with valid href' do\n      @session.click_link('labore', href: '/with_simple_html')\n      expect(@session).to have_content('Bar')\n    end\n\n    it \"should raise error if link wasn't found\" do\n      expect { @session.click_link('labore', href: 'invalid_href') }.to raise_error(Capybara::ElementNotFound, /with href \"invalid_href/)\n    end\n  end\n\n  context 'with a regex :href option given' do\n    it 'should find a link matching an all-matching regex pattern' do\n      @session.click_link('labore', href: /.+/)\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should find a link matching an exact regex pattern' do\n      @session.click_link('labore', href: %r{/with_simple_html})\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should find a link matching a partial regex pattern' do\n      @session.click_link('labore', href: %r{/with_simple})\n      expect(@session).to have_content('Bar')\n    end\n\n    it \"should raise an error if no link's href matched the pattern\" do\n      expect { @session.click_link('labore', href: /invalid_pattern/) }.to raise_error(Capybara::ElementNotFound, %r{with href matching /invalid_pattern/})\n      expect { @session.click_link('labore', href: /.+d+/) }.to raise_error(Capybara::ElementNotFound, /#{Regexp.quote 'with href matching /.+d+/'}/)\n    end\n\n    context 'href: nil' do\n      it 'should not raise an error on links with no href attribute' do\n        expect { @session.click_link('No Href', href: nil) }.not_to raise_error\n      end\n\n      it 'should raise an error if href attribute exists' do\n        expect { @session.click_link('Blank Href', href: nil) }.to raise_error(Capybara::ElementNotFound, /with no href attribute/)\n        expect { @session.click_link('Normal Anchor', href: nil) }.to raise_error(Capybara::ElementNotFound, /with no href attribute/)\n      end\n    end\n\n    context 'href: false' do\n      it 'should not raise an error on links with no href attribute' do\n        expect { @session.click_link('No Href', href: false) }.not_to raise_error\n      end\n\n      it 'should not raise an error if href attribute exists' do\n        expect { @session.click_link('Blank Href', href: false) }.not_to raise_error\n        expect { @session.click_link('Normal Anchor', href: false) }.not_to raise_error\n      end\n    end\n  end\n\n  context 'with :target option given' do\n    it 'should find links with valid target' do\n      @session.click_link('labore', target: '_self')\n      expect(@session).to have_content('Bar')\n    end\n\n    it \"should raise error if link wasn't found\" do\n      expect { @session.click_link('labore', target: '_blank') }.to raise_error(Capybara::ElementNotFound, /Unable to find link \"labore\"/)\n    end\n  end\n\n  it 'should follow relative links' do\n    @session.visit('/')\n    @session.click_link('Relative')\n    expect(@session).to have_content('This is a test')\n  end\n\n  it 'should follow protocol relative links' do\n    @session.click_link('Protocol')\n    expect(@session).to have_content('Another World')\n  end\n\n  it 'should follow redirects' do\n    @session.click_link('Redirect')\n    expect(@session).to have_content('You landed')\n  end\n\n  it 'should follow redirects back to itself' do\n    @session.click_link('BackToMyself')\n    expect(@session).to have_css('#referrer', text: %r{/with_html$})\n    expect(@session).to have_content('This is a test')\n  end\n\n  it 'should add query string to current URL with naked query string' do\n    @session.click_link('Naked Query String')\n    expect(@session).to have_content('Query String sent')\n  end\n\n  it 'should do nothing on anchor links' do\n    @session.fill_in('test_field', with: 'blah')\n    @session.click_link('Normal Anchor')\n    expect(@session.find_field('test_field').value).to eq('blah')\n    @session.click_link('Blank Anchor')\n    expect(@session.find_field('test_field').value).to eq('blah')\n    @session.click_link('Blank JS Anchor')\n    expect(@session.find_field('test_field').value).to eq('blah')\n  end\n\n  it 'should do nothing on URL+anchor links for the same page' do\n    @session.fill_in('test_field', with: 'blah')\n    @session.click_link('Anchor on same page')\n    expect(@session.find_field('test_field').value).to eq('blah')\n  end\n\n  it 'should follow link on URL+anchor links for a different page' do\n    @session.click_link('Anchor on different page')\n    expect(@session).to have_content('Bar')\n  end\n\n  it 'should follow link on anchor if the path has regex special characters' do\n    @session.visit('/with.*html')\n    @session.click_link('Anchor on different page')\n    expect(@session).to have_content('Bar')\n  end\n\n  it 'should raise an error with links with no href' do\n    expect do\n      @session.click_link('No Href')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.click_link('abo', exact: false)\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.click_link('abo', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'without locator' do\n    it 'uses options' do\n      @session.click_link(href: '/foo')\n      expect(@session).to have_content('Another World')\n    end\n  end\n\n  it 'should return element clicked' do\n    el = @session.find(:link, 'Normal Anchor')\n    expect(@session.click_link('Normal Anchor')).to eq el\n  end\n\n  it 'can download a file', requires: [:download] do\n    # This requires the driver used for the test to be configured\n    # to download documents with the mime type \"text/csv\"\n    download_file = File.join(Capybara.save_path, 'download.csv')\n    expect(File).not_to exist(download_file)\n    @session.click_link('Download Me')\n    sleep 2 # allow time for file to download\n    expect(File).to exist(download_file)\n    FileUtils.rm_rf download_file\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/current_scope_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#current_scope' do\n  before do\n    @session.visit('/with_scope')\n  end\n\n  context 'when not in a #within block' do\n    it 'should return the document' do\n      expect(@session.current_scope).to be_a Capybara::Node::Document\n    end\n  end\n\n  context 'when in a #within block' do\n    it 'should return the element in scope' do\n      @session.within(:css, '#simple_first_name') do\n        expect(@session.current_scope[:name]).to eq 'first_name'\n      end\n    end\n  end\n\n  context 'when in a nested #within block' do\n    it 'should return the element in scope' do\n      @session.within(\"//div[@id='for_bar']\") do\n        @session.within(\".//input[@value='Peter']\") do\n          expect(@session.current_scope[:name]).to eq 'form[first_name]'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/current_url_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'capybara/spec/test_app'\n\nCapybara::SpecHelper.spec '#current_url, #current_path, #current_host' do\n  before :all do # rubocop:disable RSpec/BeforeAfterAll\n    @servers = Array.new(2) { Capybara::Server.new(TestApp.new).boot }\n    # sanity check\n    expect(@servers[0].port).not_to eq(@servers[1].port) # rubocop:disable RSpec/ExpectInHook\n    expect(@servers.map(&:port)).not_to include 80 # rubocop:disable RSpec/ExpectInHook\n  end\n\n  def bases\n    @servers.map { |s| \"http://#{s.host}:#{s.port}\" }\n  end\n\n  def should_be_on(server_index, path = '/host', scheme = 'http')\n    # Check that we are on /host on the given server\n    s = @servers[server_index]\n\n    expect(@session).to have_current_path(\"#{scheme}://#{s.host}:#{s.port}#{path}\", url: true)\n\n    expect(@session.current_url.chomp('?')).to eq(\"#{scheme}://#{s.host}:#{s.port}#{path}\")\n    expect(@session.current_host).to eq(\"#{scheme}://#{s.host}\") # no port\n    expect(@session.current_path).to eq(path.split('#')[0])\n    # Server should agree with us\n    expect(@session).to have_content(\"Current host is #{scheme}://#{s.host}:#{s.port}\") if path == '/host'\n  end\n\n  def visit_host_links\n    @session.visit(\"#{bases[0]}/host_links?absolute_host=#{bases[1]}\")\n  end\n\n  it 'is affected by visiting a page directly' do\n    @session.visit(\"#{bases[0]}/host\")\n    should_be_on 0\n  end\n\n  it 'returns to the app host when visiting a relative url' do\n    Capybara.app_host = bases[1]\n    @session.visit(\"#{bases[0]}/host\")\n    should_be_on 0\n    @session.visit('/host')\n    should_be_on 1\n    Capybara.app_host = nil\n  end\n\n  it 'is affected by setting Capybara.app_host' do\n    Capybara.app_host = bases[0]\n    @session.visit('/host')\n    should_be_on 0\n    Capybara.app_host = bases[1]\n    @session.visit('/host')\n    should_be_on 1\n    Capybara.app_host = nil\n  end\n\n  it 'is unaffected by following a relative link' do\n    visit_host_links\n    @session.click_link('Relative Host')\n    should_be_on 0\n  end\n\n  it 'is affected by following an absolute link' do\n    visit_host_links\n    @session.click_link('Absolute Host')\n    should_be_on 1\n  end\n\n  it 'is unaffected by posting through a relative form' do\n    visit_host_links\n    @session.click_button('Relative Host')\n    should_be_on 0\n  end\n\n  it 'is affected by posting through an absolute form' do\n    visit_host_links\n    @session.click_button('Absolute Host')\n    should_be_on 1\n  end\n\n  it 'is affected by following a redirect' do\n    @session.visit(\"#{bases[0]}/redirect\")\n    should_be_on 0, '/landed'\n  end\n\n  it 'maintains fragment' do\n    @session.visit(\"#{bases[0]}/redirect#fragment\")\n    should_be_on 0, '/landed#fragment'\n  end\n\n  it 'redirects to a fragment' do\n    @session.visit(\"#{bases[0]}/redirect_with_fragment\")\n    should_be_on 0, '/landed#with_fragment'\n  end\n\n  it 'is affected by pushState', requires: [:js] do\n    @session.visit('/with_js')\n    @session.execute_script(\"window.history.pushState({}, '', '/pushed')\")\n    expect(@session.current_path).to eq('/pushed')\n  end\n\n  it 'is affected by replaceState', requires: [:js] do\n    @session.visit('/with_js')\n    @session.execute_script(\"window.history.replaceState({}, '', '/replaced')\")\n    expect(@session.current_path).to eq('/replaced')\n  end\n\n  it \"doesn't raise exception on a nil current_url\", requires: [:driver] do\n    allow(@session.driver).to receive(:current_url).and_return(nil)\n    @session.visit('/')\n    expect { @session.current_url }.not_to raise_exception\n    expect { @session.current_path }.not_to raise_exception\n  end\n\n  context 'within iframe', requires: [:frames] do\n    it 'should get the url of the top level browsing context' do\n      @session.visit('/within_frames')\n      expect(@session.current_url).to match(/within_frames\\z/)\n      @session.within_frame('frameOne') do\n        expect(@session.current_url).to match(/within_frames\\z/)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/dismiss_confirm_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#dismiss_confirm', requires: [:modals] do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should dismiss the confirm' do\n    @session.dismiss_confirm do\n      @session.click_link('Open confirm')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-confirm' and @confirmed='false']\")\n  end\n\n  it 'should dismiss the confirm if the message matches' do\n    @session.dismiss_confirm 'Confirm opened' do\n      @session.click_link('Open confirm')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-confirm' and @confirmed='false']\")\n  end\n\n  it \"should not dismiss the confirm if the message doesn't match\" do\n    expect do\n      @session.dismiss_confirm 'Incorrect Text' do\n        @session.click_link('Open confirm')\n      end\n    end.to raise_error(Capybara::ModalNotFound)\n  end\n\n  it 'should return the message presented' do\n    message = @session.dismiss_confirm do\n      @session.click_link('Open confirm')\n    end\n    expect(message).to eq('Confirm opened')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/dismiss_prompt_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#dismiss_prompt', requires: [:modals] do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should dismiss the prompt' do\n    @session.dismiss_prompt do\n      @session.click_link('Open prompt')\n    end\n    expect(@session).to have_xpath(\"//a[@id='open-prompt' and @response='dismissed']\")\n  end\n\n  it 'should return the message presented' do\n    message = @session.dismiss_prompt do\n      @session.click_link('Open prompt')\n    end\n    expect(message).to eq('Prompt opened')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/element/assert_match_selector_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#assert_matches_selector' do\n  before do\n    @session.visit('/with_html')\n    @element = @session.find(:css, 'span', text: '42')\n  end\n\n  it 'should be true if the given selector matches the element' do\n    expect(@element.assert_matches_selector(:css, '.number')).to be true\n  end\n\n  it 'should be false if the given selector does not match the element' do\n    expect { @element.assert_matches_selector(:css, '.not_number') }.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should not be callable on the session' do\n    expect { @session.assert_matches_selector(:css, '.number') }.to raise_error(NoMethodError)\n  end\n\n  it 'should wait for match to occur', requires: [:js] do\n    @session.visit('/with_js')\n    input = @session.find(:css, '#disable-on-click')\n\n    expect(input.assert_matches_selector(:css, 'input:enabled')).to be true\n    input.click\n    expect(input.assert_matches_selector(:css, 'input:disabled')).to be true\n  end\n\n  it 'should not accept count options' do\n    expect { @element.assert_matches_selector(:css, '.number', count: 1) }.to raise_error(ArgumentError, /count/)\n  end\n\n  it 'should accept a filter block' do\n    @element.assert_matches_selector(:css, 'span') { |el| el[:class] == 'number' }\n    @element.assert_not_matches_selector(:css, 'span') { |el| el[:class] == 'not_number' }\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/element/match_css_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#match_css?' do\n  before do\n    @session.visit('/with_html')\n    @element = @session.find(:css, 'span', text: '42')\n  end\n\n  it 'should be true if the given selector matches the element' do\n    expect(@element).to match_css('span')\n    expect(@element).to match_css('span.number')\n  end\n\n  it 'should be false if the given selector does not match' do\n    expect(@element).not_to match_css('div')\n    expect(@element).not_to match_css('p a#doesnotexist')\n    expect(@element).not_to match_css('p.nosuchclass')\n  end\n\n  it 'should accept an optional filter block' do\n    # This would be better done with\n    expect(@element).to match_css('span') { |el| el[:class] == 'number' }\n    expect(@element).not_to match_css('span') { |el| el[:class] == 'not_number' }\n  end\n\n  it 'should work with root element found via ancestor' do\n    el = @session.find(:css, 'body').find(:xpath, '..')\n    expect(el).to match_css('html')\n    expect { expect(el).to not_match_css('html') }.to raise_exception(RSpec::Expectations::ExpectationNotMetError)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/element/match_xpath_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#match_xpath?' do\n  before do\n    @session.visit('/with_html')\n    @element = @session.find(:css, 'span.number')\n  end\n\n  it 'should be true if the given selector is on the page' do\n    expect(@element).to match_xpath('//span')\n    expect(@element).to match_xpath(\"//span[@class='number']\")\n  end\n\n  it 'should be false if the given selector is not on the page' do\n    expect(@element).not_to match_xpath('//abbr')\n    expect(@element).not_to match_xpath('//div')\n    expect(@element).not_to match_xpath(\"//span[@class='not_a_number']\")\n  end\n\n  it 'should use xpath even if default selector is CSS' do\n    Capybara.default_selector = :css\n    expect(@element).not_to have_xpath(\"//span[@class='not_a_number']\")\n    expect(@element).not_to have_xpath(\"//div[@class='number']\")\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/element/matches_selector_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#match_selector?' do\n  let(:element) { @session.find(:xpath, '//span', text: '42') }\n\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the element matches the given selector' do\n    expect(element).to match_selector(:xpath, '//span')\n    expect(element).to match_selector(:css, 'span.number')\n    expect(element.matches_selector?(:css, 'span.number')).to be true\n  end\n\n  it 'should be false if the element does not match the given selector' do\n    expect(element).not_to match_selector(:xpath, '//div')\n    expect(element).not_to match_selector(:css, 'span.not_a_number')\n    expect(element.matches_selector?(:css, 'span.not_a_number')).to be false\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(element).not_to match_selector('span.not_a_number')\n    expect(element).to match_selector('span.number')\n  end\n\n  it 'should work with elements located via a sibling selector' do\n    sibling = element.sibling(:css, 'span', text: 'Other span')\n    expect(sibling).to match_selector(:xpath, '//span')\n    expect(sibling).to match_selector(:css, 'span')\n  end\n\n  it 'should work with the html element' do\n    html = @session.find('/html')\n    expect(html).to match_selector(:css, 'html')\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      expect(element).to match_selector('//span', text: '42')\n      expect(element).not_to match_selector('//span', text: 'Doesnotexist')\n    end\n  end\n\n  it 'should have css sugar' do\n    expect(element.matches_css?('span.number')).to be true\n    expect(element.matches_css?('span.not_a_number')).to be false\n    expect(element.matches_css?('span.number', text: '42')).to be true\n    expect(element.matches_css?('span.number', text: 'Nope')).to be false\n  end\n\n  it 'should have xpath sugar' do\n    expect(element.matches_xpath?('//span')).to be true\n    expect(element.matches_xpath?('//div')).to be false\n    expect(element.matches_xpath?('//span', text: '42')).to be true\n    expect(element.matches_xpath?('//span', text: 'Nope')).to be false\n  end\n\n  it 'should accept selector filters' do\n    @session.visit('/form')\n    cbox = @session.find(:css, '#form_pets_dog')\n    expect(cbox.matches_selector?(:checkbox, id: 'form_pets_dog', option: 'dog', name: 'form[pets][]', checked: true)).to be true\n  end\n\n  it 'should accept a custom filter block' do\n    @session.visit('/form')\n    cbox = @session.find(:css, '#form_pets_dog')\n    expect(cbox).to match_selector(:checkbox) { |node| node[:id] == 'form_pets_dog' }\n    expect(cbox).not_to match_selector(:checkbox) { |node| node[:id] != 'form_pets_dog' }\n    expect(cbox.matches_selector?(:checkbox) { |node| node[:id] == 'form_pets_dog' }).to be true\n    expect(cbox.matches_selector?(:checkbox) { |node| node[:id] != 'form_pets_dog' }).to be false\n  end\nend\n\nCapybara::SpecHelper.spec '#not_matches_selector?' do\n  let(:element) { @session.find(:css, 'span', text: 42) }\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given selector matches the element' do\n    expect(element).not_to not_match_selector(:xpath, '//span')\n    expect(element).not_to not_match_selector(:css, 'span.number')\n    expect(element.not_matches_selector?(:css, 'span.number')).to be false\n  end\n\n  it 'should be true if the given selector does not match the element' do\n    expect(element).to not_match_selector(:xpath, '//abbr')\n    expect(element).to not_match_selector(:css, 'p a#doesnotexist')\n    expect(element.not_matches_selector?(:css, 'p a#doesnotexist')).to be true\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(element).to not_match_selector('p a#doesnotexist')\n    expect(element).not_to not_match_selector('span.number')\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is contained' do\n      expect(element).not_to not_match_selector(:css, 'span.number', text: '42')\n      expect(element).to not_match_selector(:css, 'span.number', text: 'Doesnotexist')\n    end\n  end\n\n  it 'should have CSS sugar' do\n    expect(element.not_matches_css?('span.number')).to be false\n    expect(element.not_matches_css?('p a#doesnotexist')).to be true\n    expect(element.not_matches_css?('span.number', text: '42')).to be false\n    expect(element.not_matches_css?('span.number', text: 'Doesnotexist')).to be true\n  end\n\n  it 'should have xpath sugar' do\n    expect(element.not_matches_xpath?('//span')).to be false\n    expect(element.not_matches_xpath?('//div')).to be true\n    expect(element.not_matches_xpath?('//span', text: '42')).to be false\n    expect(element.not_matches_xpath?('//span', text: 'Doesnotexist')).to be true\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/evaluate_async_script_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#evaluate_async_script', requires: [:js] do\n  it 'should evaluate the given script and return whatever it produces' do\n    @session.visit('/with_js')\n    expect(@session.evaluate_async_script('arguments[0](4)')).to eq(4)\n  end\n\n  it 'should support passing elements as arguments to the script', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    el = @session.find(:css, '#drag p')\n    result = @session.evaluate_async_script('arguments[2]([arguments[0].innerText, arguments[1]])', el, 'Doodle Funk')\n    expect(result).to eq ['This is a draggable element.', 'Doodle Funk']\n  end\n\n  it 'should support returning elements after asynchronous operation', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    @session.find(:css, '#change') # ensure page has loaded and element is available\n    el = @session.evaluate_async_script(\"var cb = arguments[0]; setTimeout(function(){ cb(document.getElementById('change')) }, 100)\")\n    expect(el).to be_instance_of(Capybara::Node::Element)\n    expect(el).to eq(@session.find(:css, '#change'))\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/evaluate_script_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#evaluate_script', requires: [:js] do\n  it 'should evaluate the given script and return whatever it produces' do\n    @session.visit('/with_js')\n    expect(@session.evaluate_script('1+3')).to eq(4)\n  end\n\n  it 'should ignore leading whitespace' do\n    @session.visit('/with_js')\n    expect(@session.evaluate_script('\n      1 + 3\n    ')).to eq(4)\n  end\n\n  it 'should pass arguments to the script', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    expect(@session).to have_css('#change')\n    @session.evaluate_script(\"document.getElementById('change').textContent = arguments[0]\", 'Doodle Funk')\n    expect(@session).to have_css('#change', text: 'Doodle Funk')\n  end\n\n  it 'should support passing elements as arguments to the script', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    el = @session.find(:css, '#change')\n    @session.evaluate_script('arguments[0].textContent = arguments[1]', el, 'Doodle Funk')\n    expect(@session).to have_css('#change', text: 'Doodle Funk')\n  end\n\n  it 'should support returning elements', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    @session.find(:css, '#change') # ensure page has loaded and element is available\n    el = @session.evaluate_script(\"document.getElementById('change')\")\n    expect(el).to be_instance_of(Capybara::Node::Element)\n    expect(el).to eq(@session.find(:css, '#change'))\n  end\n\n  it 'should support multi statement via IIFE' do\n    @session.visit('/with_js')\n    @session.find(:css, '#change')\n    el = @session.evaluate_script(<<~JS)\n      (function(){\n        var el = document.getElementById('change');\n        return el;\n      })()\n    JS\n    expect(el).to eq(@session.find(:css, '#change'))\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/execute_script_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#execute_script', requires: [:js] do\n  it 'should execute the given script and return nothing' do\n    @session.visit('/with_js')\n    expect(@session.execute_script(\"document.getElementById('change').textContent = 'Funky Doodle'\")).to be_nil\n    expect(@session).to have_css('#change', text: 'Funky Doodle')\n  end\n\n  it 'should be able to call functions defined in the page' do\n    @session.visit('/with_js')\n    expect { @session.execute_script(\"$('#change').text('Funky Doodle')\") }.not_to raise_error\n  end\n\n  it 'should pass arguments to the script', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    expect(@session).to have_css('#change')\n    @session.execute_script(\"document.getElementById('change').textContent = arguments[0]\", 'Doodle Funk')\n    expect(@session).to have_css('#change', text: 'Doodle Funk')\n  end\n\n  it 'should support passing elements as arguments to the script', requires: %i[js es_args] do\n    @session.visit('/with_js')\n    el = @session.find(:css, '#change')\n    @session.execute_script('arguments[1].textContent = arguments[0]', 'Doodle Funk', el)\n    expect(@session).to have_css('#change', text: 'Doodle Funk')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/fill_in_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#fill_in' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should fill in a text field by id' do\n    @session.fill_in('form_first_name', with: 'Harry')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['first_name']).to eq('Harry')\n  end\n\n  it 'should fill in a text field by name' do\n    @session.fill_in('form[last_name]', with: 'Green')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['last_name']).to eq('Green')\n  end\n\n  it 'should fill in a text field by label without for' do\n    @session.fill_in('First Name', with: 'Harry')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['first_name']).to eq('Harry')\n  end\n\n  it 'should fill in a url field by label without for' do\n    @session.fill_in('Html5 Url', with: 'http://www.avenueq.com')\n    @session.click_button('html5_submit')\n    expect(extract_results(@session)['html5_url']).to eq('http://www.avenueq.com')\n  end\n\n  it 'should fill in a textarea by id' do\n    @session.fill_in('form_description', with: 'Texty text')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq('Texty text')\n  end\n\n  it 'should fill in a textarea by label' do\n    @session.fill_in('Description', with: 'Texty text')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq('Texty text')\n  end\n\n  it 'should fill in a textarea by name' do\n    @session.fill_in('form[description]', with: 'Texty text')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq('Texty text')\n  end\n\n  it 'should fill in a textarea in a reasonable time by default' do\n    textarea = @session.find(:fillable_field, 'form[description]')\n    value = 'a' * 4000\n    start = Time.now\n    textarea.fill_in(with: value)\n    expect(Time.now.to_f).to be_within(0.25).of start.to_f\n    expect(textarea.value).to eq value\n  end\n\n  it 'should fill in a password field by id' do\n    @session.fill_in('form_password', with: 'supasikrit')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['password']).to eq('supasikrit')\n  end\n\n  context 'Date/Time' do\n    it 'should fill in a date input' do\n      date = Date.today\n      @session.fill_in('form_date', with: date)\n      @session.click_button('awesome')\n      expect(Date.parse(extract_results(@session)['date'])).to eq date\n    end\n\n    it 'should fill in a time input' do\n      time = Time.new(2018, 3, 9, 15, 26)\n      @session.fill_in('form_time', with: time)\n      @session.click_button('awesome')\n      results = extract_results(@session)['time']\n      expect(Time.parse(results).strftime('%r')).to eq time.strftime('%r')\n    end\n\n    it 'should fill in a datetime input' do\n      dt = Time.new(2018, 3, 13, 9, 53)\n      @session.fill_in('form_datetime', with: dt)\n      @session.click_button('awesome')\n      expect(Time.parse(extract_results(@session)['datetime'])).to eq dt\n    end\n  end\n\n  it 'should handle HTML in a textarea' do\n    @session.fill_in('form_description', with: 'is <strong>very</strong> secret!')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq('is <strong>very</strong> secret!')\n  end\n\n  it 'should handle newlines in a textarea' do\n    @session.fill_in('form_description', with: \"\\nSome text\\n\")\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq(\"\\r\\nSome text\\r\\n\")\n  end\n\n  it 'should handle carriage returns with line feeds in a textarea correctly' do\n    @session.fill_in('form_description', with: \"\\r\\nSome text\\r\\n\")\n    @session.click_button('awesome')\n    expect(extract_results(@session)['description']).to eq(\"\\r\\nSome text\\r\\n\")\n  end\n\n  it 'should fill in a color field' do\n    @session.fill_in('Html5 Color', with: '#112233')\n    @session.click_button('html5_submit')\n    expect(extract_results(@session)['html5_color']).to eq('#112233')\n  end\n\n  describe 'with input[type=\"range\"]' do\n    it 'should set the range slider correctly' do\n      @session.fill_in('form_age', with: 51)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['age'].to_f).to eq 51\n    end\n\n    it 'should set the range slider to valid values' do\n      @session.fill_in('form_age', with: '37.6')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['age'].to_f).to eq 37.5\n    end\n\n    it 'should respect the range slider limits' do\n      @session.fill_in('form_age', with: '3')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['age'].to_f).to eq 13\n    end\n  end\n\n  it 'should fill in a field with a custom type' do\n    @session.fill_in('Schmooo', with: 'Schmooo is the game')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['schmooo']).to eq('Schmooo is the game')\n  end\n\n  it 'should fill in a field without a type' do\n    @session.fill_in('Phone', with: '+1 555 7022')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['phone']).to eq('+1 555 7022')\n  end\n\n  it 'should fill in a text field respecting its maxlength attribute' do\n    @session.fill_in('Zipcode', with: '52071350')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['zipcode']).to eq('52071')\n  end\n\n  it 'should fill in a password field by name' do\n    @session.fill_in('form[password]', with: 'supasikrit')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['password']).to eq('supasikrit')\n  end\n\n  it 'should fill in a password field by label' do\n    @session.fill_in('Password', with: 'supasikrit')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['password']).to eq('supasikrit')\n  end\n\n  it 'should fill in a password field by name' do\n    @session.fill_in('form[password]', with: 'supasikrit')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['password']).to eq('supasikrit')\n  end\n\n  it 'should fill in a field based on current value' do\n    @session.fill_in(id: /form.*name/, currently_with: 'John', with: 'Thomas')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['first_name']).to eq('Thomas')\n  end\n\n  it 'should fill in a field based on type' do\n    @session.fill_in(type: 'schmooo', with: 'Schmooo for all')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['schmooo']).to eq('Schmooo for all')\n  end\n\n  it 'should be able to fill in element called on when no locator passed' do\n    field = @session.find(:fillable_field, 'form[password]')\n    field.fill_in(with: 'supasikrit')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['password']).to eq('supasikrit')\n  end\n\n  it \"should throw an exception if a hash containing 'with' is not provided\" do\n    expect { @session.fill_in 'Name' }.to raise_error(ArgumentError, /with/)\n  end\n\n  it 'should wait for asynchronous load', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    @session.fill_in('new_field', with: 'Testing...')\n  end\n\n  it 'casts to string' do\n    @session.fill_in(:form_first_name, with: :Harry)\n    @session.click_button('awesome')\n    expect(extract_results(@session)['first_name']).to eq('Harry')\n  end\n\n  it 'casts to string if field has maxlength' do\n    @session.fill_in(:form_zipcode, with: 1234567)\n    @session.click_button('awesome')\n    expect(extract_results(@session)['zipcode']).to eq('12345')\n  end\n\n  it 'fills in a field if default_set_options is nil' do\n    Capybara.default_set_options = nil\n    @session.fill_in(:form_first_name, with: 'Thomas')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['first_name']).to eq('Thomas')\n  end\n\n  context 'on a pre-populated textfield with a reformatting onchange', requires: [:js] do\n    it 'should only trigger onchange once' do\n      @session.visit('/with_js')\n      # Click somewhere on the page to ensure focus is acquired. Without this FF won't generate change events for some reason???\n      @session.find(:css, 'h1', text: 'FooBar').click\n      @session.fill_in('with_change_event', with: 'some value')\n      # click outside the field to trigger the change event\n      @session.find(:css, 'h1', text: 'FooBar').click\n      expect(@session.find(:css, '.change_event_triggered', match: :one)).to have_text 'some value'\n    end\n\n    it 'should trigger change when clearing field' do\n      @session.visit('/with_js')\n      @session.fill_in('with_change_event', with: '')\n      # click outside the field to trigger the change event\n      @session.find(:css, 'h1', text: 'FooBar').click\n      expect(@session).to have_selector(:css, '.change_event_triggered', match: :one)\n    end\n  end\n\n  context 'with ignore_hidden_fields' do\n    before { Capybara.ignore_hidden_elements = true }\n\n    after  { Capybara.ignore_hidden_elements = false }\n\n    it 'should not find a hidden field' do\n      msg = /Unable to find visible field \"Super Secret\"/\n      expect do\n        @session.fill_in('Super Secret', with: '777')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find field \"does not exist\"/\n      expect do\n        @session.fill_in('does not exist', with: 'Blah blah')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'on a disabled field' do\n    it 'should raise an error' do\n      expect do\n        @session.fill_in('Disabled Text Field', with: 'Blah blah')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.fill_in('Explanation', with: 'Dude', exact: false)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['name_explanation']).to eq('Dude')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.fill_in('Explanation', with: 'Dude', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  it 'should return the element filled in' do\n    el = @session.find(:fillable_field, 'form_first_name')\n    expect(@session.fill_in('form_first_name', with: 'Harry')).to eq el\n  end\n\n  it 'should warn if passed what looks like a CSS id selector' do\n    expect do\n      @session.fill_in('#form_first_name', with: 'Harry')\n    end.to raise_error(/you may be passing a CSS selector or XPath expression rather than a locator/)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/find_button_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#find_button' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should find any button' do\n    expect(@session.find_button('med')[:id]).to eq('mediocre')\n    expect(@session.find_button('crap321').value).to eq('crappy')\n  end\n\n  context 'aria_label attribute with Capybara.enable_aria_label' do\n    it 'should find when true' do\n      Capybara.enable_aria_label = true\n      expect(@session.find_button('Mediocre Button')[:id]).to eq('mediocre')\n    end\n\n    it 'should not find when false' do\n      Capybara.enable_aria_label = false\n      expect { @session.find_button('Mediocre Button') }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  it 'casts to string' do\n    expect(@session.find_button(:med)[:id]).to eq('mediocre')\n  end\n\n  it \"should raise error if the button doesn't exist\" do\n    expect do\n      @session.find_button('Does not exist')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      expect(@session.find_button('What an Awesome', exact: false).value).to eq('awesome')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.find_button('What an Awesome', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with :disabled option' do\n    it 'should find disabled buttons when true' do\n      expect(@session.find_button('Disabled button', disabled: true).value).to eq('Disabled button')\n    end\n\n    it 'should not find disabled buttons when false' do\n      expect do\n        @session.find_button('Disabled button', disabled: false)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should default to not finding disabled buttons' do\n      expect do\n        @session.find_button('Disabled button')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should find disabled buttons when :all' do\n      expect(@session.find_button('Disabled button', disabled: :all).value).to eq('Disabled button')\n    end\n  end\n\n  context 'without locator' do\n    it 'should use options' do\n      expect(@session.find_button(disabled: true).value).to eq('Disabled button')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/find_by_id_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#find_by_id' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should find any element by id' do\n    expect(@session.find_by_id('red').tag_name).to eq('a')\n  end\n\n  it 'casts to string' do\n    expect(@session.find_by_id(:red).tag_name).to eq('a')\n  end\n\n  it 'should raise error if no element with id is found' do\n    expect do\n      @session.find_by_id('nothing_with_this_id')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  context 'with :visible option' do\n    it 'finds invisible elements when `false`' do\n      expect(@session.find_by_id('hidden_via_ancestor', visible: false).text(:all)).to match(/with hidden ancestor/)\n    end\n\n    it \"doesn't find invisible elements when `true`\" do\n      expect do\n        @session.find_by_id('hidden_via_ancestor', visible: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/find_field_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#find_field' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should find any field' do\n    Capybara.test_id = 'data-test-id'\n    expect(@session.find_field('Dog').value).to eq('dog')\n    expect(@session.find_field('form_description').value).to eq('Descriptive text goes here')\n    expect(@session.find_field('Region')[:name]).to eq('form[region]')\n    expect(@session.find_field('With Asterisk*')).to be_truthy\n    expect(@session.find_field('my_test_id')).to be_truthy\n  end\n\n  context 'aria_label attribute with Capybara.enable_aria_label' do\n    it 'should find when true' do\n      Capybara.enable_aria_label = true\n      expect(@session.find_field('Unlabelled Input')[:name]).to eq('form[which_form]')\n      # expect(@session.find_field('Emergency Number')[:id]).to eq('html5_tel')\n    end\n\n    it 'should not find when false' do\n      Capybara.enable_aria_label = false\n      expect { @session.find_field('Unlabelled Input') }.to raise_error(Capybara::ElementNotFound)\n      # expect { @session.find_field('Emergency Number') }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  it 'casts to string' do\n    expect(@session.find_field(:Dog).value).to eq('dog')\n  end\n\n  it \"should raise error if the field doesn't exist\" do\n    expect do\n      @session.find_field('Does not exist')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should raise error if filter option is invalid' do\n    expect do\n      @session.find_field('Dog', disabled: nil)\n    end.to raise_error ArgumentError, 'Invalid value nil passed to NodeFilter disabled'\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      expect(@session.find_field('Explanation', exact: false)[:name]).to eq('form[name_explanation]')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.find_field('Explanation', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with :disabled option' do\n    it 'should find disabled fields when true' do\n      expect(@session.find_field('Disabled Checkbox', disabled: true)[:name]).to eq('form[disabled_checkbox]')\n      expect(@session.find_field('form_disabled_fieldset_child', disabled: true)[:name]).to eq('form[disabled_fieldset_child]')\n      expect(@session.find_field('form_disabled_fieldset_descendant', disabled: true)[:name]).to eq('form[disabled_fieldset_descendant]')\n    end\n\n    it 'should not find disabled fields when false' do\n      expect do\n        @session.find_field('Disabled Checkbox', disabled: false)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should not find disabled fields by default' do\n      expect do\n        @session.find_field('Disabled Checkbox')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should find disabled fields when :all' do\n      expect(@session.find_field('Disabled Checkbox', disabled: :all)[:name]).to eq('form[disabled_checkbox]')\n    end\n\n    it 'should find enabled fields when :all' do\n      expect(@session.find_field('Dog', disabled: :all).value).to eq('dog')\n    end\n  end\n\n  context 'with :readonly option' do\n    it 'should find readonly fields when true' do\n      expect(@session.find_field('form[readonly_test]', readonly: true)[:id]).to eq 'readonly'\n    end\n\n    it 'should not find readonly fields when false' do\n      expect(@session.find_field('form[readonly_test]', readonly: false)[:id]).to eq 'not_readonly'\n    end\n\n    it 'should ignore readonly by default' do\n      expect do\n        @session.find_field('form[readonly_test]')\n      end.to raise_error(Capybara::Ambiguous, /found 2 elements/)\n    end\n  end\n\n  context 'with no locator' do\n    it 'should use options to find the field' do\n      expect(@session.find_field(type: 'checkbox', with: 'dog')['id']).to eq 'form_pets_dog'\n    end\n  end\n\n  it 'should accept an optional filter block' do\n    # this would be better done with the :with option but this is just a test\n    expect(@session.find_field('form[pets][]') { |node| node.value == 'dog' }[:id]).to eq 'form_pets_dog'\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/find_link_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#find_link' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should find any link' do\n    expect(@session.find_link('foo').text).to eq('ullamco')\n    expect(@session.find_link('labore')[:href]).to match %r{/with_simple_html$}\n  end\n\n  context 'aria_label attribute with Capybara.enable_aria_label' do\n    it 'should find when true' do\n      Capybara.enable_aria_label = true\n      expect(@session.find_link('Go to simple')[:href]).to match %r{/with_simple_html$}\n    end\n\n    it 'should not find when false' do\n      Capybara.enable_aria_label = false\n      expect { @session.find_link('Go to simple') }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  it 'casts to string' do\n    expect(@session.find_link(:foo).text).to eq('ullamco')\n  end\n\n  it \"should raise error if the field doesn't exist\" do\n    expect do\n      @session.find_link('Does not exist')\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      expect(@session.find_link('abo', exact: false).text).to eq('labore')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.find_link('abo', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'without locator' do\n    it 'should use options' do\n      expect(@session.find_link(href: '#anchor').text).to eq 'Normal Anchor'\n    end\n  end\n\n  context 'download filter' do\n    it 'finds a download link' do\n      expect(@session.find_link('Download Me', download: true).text).to eq 'Download Me'\n    end\n\n    it \"doesn't find a download link if download is false\" do\n      expect { @session.find_link('Download Me', download: false) }.to raise_error Capybara::ElementNotFound\n    end\n\n    it 'finds a renaming download link' do\n      expect(@session.find_link(download: 'other.csv').text).to eq 'Download Other'\n    end\n\n    it 'raises if passed an invalid value' do\n      expect { @session.find_link(download: 37) }.to raise_error ArgumentError\n    end\n  end\n\n  context 'with :target option' do\n    it 'should accept partial matches when false' do\n      expect(@session.find_link(target: '_self').text).to eq('labore')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect { @session.find_link(target: '_blank') }.to raise_error Capybara::ElementNotFound\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/find_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#find' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  after do\n    Capybara::Selector.remove(:monkey)\n  end\n\n  it 'should find the first element using the given locator' do\n    expect(@session.find('//h1').text).to eq('This is a test')\n    expect(@session.find(\"//input[@id='test_field']\").value).to eq('monkey')\n  end\n\n  it 'should find the first element using the given locator and options' do\n    expect(@session.find('//a', text: 'Redirect')[:id]).to eq('red')\n    expect(@session.find(:css, 'a', text: 'A link came first')[:title]).to eq('twas a fine link')\n  end\n\n  it 'should raise an error if there are multiple matches' do\n    expect { @session.find('//a') }.to raise_error(Capybara::Ambiguous)\n  end\n\n  it 'should wait for asynchronous load', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session.find(:css, 'a#has-been-clicked').text).to include('Has been clicked')\n  end\n\n  context 'with :text option' do\n    it \"casts text's argument to string\" do\n      expect(@session.find(:css, '.number', text: 42)).to have_content('42')\n    end\n  end\n\n  context 'with :wait option', requires: [:js] do\n    it 'should not wait for asynchronous load when `false` given' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect do\n        @session.find(:css, 'a#has-been-clicked', wait: false)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should not find element if it appears after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Slowly')\n      expect do\n        @session.find(:css, 'a#slow-clicked', wait: 0.2)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should find element if it appears before given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect(@session.find(:css, 'a#has-been-clicked', wait: 3.0).text).to include('Has been clicked')\n    end\n  end\n\n  context 'with frozen time', requires: [:js] do\n    if defined?(Process::CLOCK_MONOTONIC)\n      it 'will time out even if time is frozen' do\n        @session.visit('/with_js')\n        now = Time.now\n        allow(Time).to receive(:now).and_return(now)\n        expect { @session.find('//isnotthere') }.to raise_error(Capybara::ElementNotFound)\n      end\n    else\n      it 'raises an error suggesting that Capybara is stuck in time' do\n        @session.visit('/with_js')\n        now = Time.now\n        allow(Time).to receive(:now).and_return(now)\n        expect { @session.find('//isnotthere') }.to raise_error(Capybara::FrozenInTime)\n      end\n    end\n  end\n\n  context 'with css selectors' do\n    it 'should find the first element using the given locator' do\n      expect(@session.find(:css, 'h1').text).to eq('This is a test')\n      expect(@session.find(:css, \"input[id='test_field']\").value).to eq('monkey')\n    end\n\n    it 'should support pseudo selectors' do\n      expect(@session.find(:css, 'input:disabled').value).to eq('This is disabled')\n    end\n\n    it 'should support escaping characters' do\n      expect(@session.find(:css, '#\\31 escape\\.me').text).to eq('needs escaping')\n      expect(@session.find(:css, '.\\32 escape').text).to eq('needs escaping')\n    end\n\n    it 'should not warn about locator' do\n      expect { @session.find(:css, '#not_on_page') }.to raise_error Capybara::ElementNotFound do |e|\n        expect(e.message).not_to match(/you may be passing a CSS selector or XPath expression/)\n      end\n    end\n  end\n\n  context 'with xpath selectors' do\n    it 'should find the first element using the given locator' do\n      expect(@session.find(:xpath, '//h1').text).to eq('This is a test')\n      expect(@session.find(:xpath, \"//input[@id='test_field']\").value).to eq('monkey')\n    end\n\n    it 'should warn if passed a non-valid locator type' do\n      expect { @session.find(:xpath, 123) }.to raise_error(Exception) # The exact error is not yet well defined\n        .and output(/must respond to to_xpath or be an instance of String/).to_stderr\n    end\n  end\n\n  context 'with custom selector' do\n    it 'should use the custom selector' do\n      Capybara.add_selector(:beatle) do\n        xpath { |name| \".//*[@id='#{name}']\" }\n      end\n      expect(@session.find(:beatle, 'john').text).to eq('John')\n      expect(@session.find(:beatle, 'paul').text).to eq('Paul')\n    end\n  end\n\n  context 'with custom selector with custom `match` block' do\n    it 'should use the custom selector when locator matches the block' do\n      Capybara.add_selector(:beatle) do\n        xpath { |num| \".//*[contains(@class, 'beatle')][#{num}]\" }\n        match { |value| value.is_a?(Integer) }\n      end\n      expect(@session.find(:beatle, '2').text).to eq('Paul')\n      expect(@session.find(1).text).to eq('John')\n      expect(@session.find(2).text).to eq('Paul')\n      expect(@session.find('//h1').text).to eq('This is a test')\n    end\n  end\n\n  context 'with custom selector with custom filter' do\n    before do\n      Capybara.add_selector(:beatle) do\n        xpath { |name| \".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]\" }\n        node_filter(:type) { |node, type| node[:class].split(/\\s+/).include?(type) }\n        node_filter(:fail) { |_node, _val| raise Capybara::ElementNotFound, 'fail' }\n      end\n    end\n\n    it 'should find elements that match the filter' do\n      expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')\n      expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')\n    end\n\n    it 'ignores filter when it is not given' do\n      expect(@session.find(:beatle, 'Paul').text).to eq('Paul')\n      expect(@session.find(:beatle, 'John').text).to eq('John')\n    end\n\n    it \"should not find elements that don't match the filter\" do\n      expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should not raise an ElementNotFound error from in a filter' do\n      expect { @session.find(:beatle, 'John', fail: 'something') }.to raise_error(Capybara::ElementNotFound, /beatle \"John\"/)\n    end\n  end\n\n  context 'with custom selector with custom filter and default' do\n    before do\n      Capybara.add_selector(:beatle) do\n        xpath { |name| \".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]\" }\n        node_filter(:type, default: 'drummer') { |node, type| node[:class].split(/\\s+/).include?(type) }\n      end\n    end\n\n    it 'should find elements that match the filter' do\n      expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')\n      expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')\n    end\n\n    it 'should use default value when filter is not given' do\n      expect(@session.find(:beatle, 'Paul').text).to eq('Paul')\n      expect { @session.find(:beatle, 'John') }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it \"should not find elements that don't match the filter\" do\n      expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)\n      expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with alternate filter set' do\n    before do\n      Capybara::Selector::FilterSet.add(:value) do\n        node_filter(:with) { |node, with| node.value == with.to_s }\n      end\n\n      Capybara.add_selector(:id_with_field_filters) do\n        xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }\n        filter_set(:field)\n      end\n    end\n\n    it 'should allow use of filters from custom filter set' do\n      expect(@session.find(:id, 'test_field', filter_set: :value, with: 'monkey').value).to eq('monkey')\n      expect { @session.find(:id, 'test_field', filter_set: :value, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should allow use of filter set from a different selector' do\n      expect(@session.find(:id, 'test_field', filter_set: :field, with: 'monkey').value).to eq('monkey')\n      expect { @session.find(:id, 'test_field', filter_set: :field, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'should allow importing of filter set into selector' do\n      expect(@session.find(:id_with_field_filters, 'test_field', with: 'monkey').value).to eq('monkey')\n      expect { @session.find(:id_with_field_filters, 'test_field', with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'with css as default selector' do\n    before { Capybara.default_selector = :css }\n\n    after { Capybara.default_selector = :xpath }\n\n    it 'should find the first element using the given locator' do\n      expect(@session.find('h1').text).to eq('This is a test')\n      expect(@session.find(\"input[id='test_field']\").value).to eq('monkey')\n    end\n  end\n\n  it 'should raise ElementNotFound with a useful default message if nothing was found' do\n    expect do\n      @session.find(:xpath, '//div[@id=\"nosuchthing\"]').to be_nil\n    end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath \"//div[@id=\\\\\"nosuchthing\\\\\"]\"')\n  end\n\n  context 'without locator' do\n    it 'should not output `nil` in the ElementNotFound message if nothing was found' do\n      expect do\n        @session.find(:label, text: 'no such thing').to be_nil\n      end.to raise_error(Capybara::ElementNotFound, 'Unable to find label')\n    end\n  end\n\n  it 'should accept an XPath instance' do\n    @session.visit('/form')\n    @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')\n    expect(@xpath).to be_a(XPath::Union)\n    expect(@session.find(@xpath).value).to eq('John')\n  end\n\n  context 'with :exact option' do\n    it 'matches exactly when true' do\n      expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: true).value).to eq('monkey')\n      expect do\n        @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n\n    it 'matches loosely when false' do\n      expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: false).value).to eq('monkey')\n      expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: false).value).to eq('monkey')\n    end\n\n    it 'defaults to `Capybara.exact`' do\n      Capybara.exact = true\n      expect do\n        @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])\n      end.to raise_error(Capybara::ElementNotFound)\n      Capybara.exact = false\n      @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])\n    end\n\n    it 'warns when the option has no effect' do\n      expect { @session.find(:css, '#test_field', exact: true) }.to \\\n        output(/^The :exact option only has an effect on queries using the XPath#is method. Using it with the query \"#test_field\" has no effect/).to_stderr\n    end\n  end\n\n  context 'with :match option' do\n    context 'when set to `one`' do\n      it 'raises an error when multiple matches exist' do\n        expect do\n          @session.find(:css, '.multiple', match: :one)\n        end.to raise_error(Capybara::Ambiguous)\n      end\n\n      it 'raises an error even if there the match is exact and the others are inexact' do\n        expect do\n          @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], exact: false, match: :one)\n        end.to raise_error(Capybara::Ambiguous)\n      end\n\n      it 'returns the element if there is only one' do\n        expect(@session.find(:css, '.singular', match: :one).text).to eq('singular')\n      end\n\n      it 'raises an error if there is no match' do\n        expect do\n          @session.find(:css, '.does-not-exist', match: :one)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n\n    context 'when set to `first`' do\n      it 'returns the first matched element' do\n        expect(@session.find(:css, '.multiple', match: :first).text).to eq('multiple one')\n      end\n\n      it 'raises an error if there is no match' do\n        expect do\n          @session.find(:css, '.does-not-exist', match: :first)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n\n    context 'when set to `smart`' do\n      context 'and `exact` set to `false`' do\n        it 'raises an error when there are multiple exact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: false)\n          end.to raise_error(Capybara::Ambiguous)\n        end\n\n        it 'finds a single exact match when there also are inexact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: false)\n          expect(result.text).to eq('almost singular')\n        end\n\n        it 'raises an error when there are multiple inexact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: false)\n          end.to raise_error(Capybara::Ambiguous)\n        end\n\n        it 'finds a single inexact match' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: false)\n          expect(result.text).to eq('almost singular but not quite')\n        end\n\n        it 'raises an error if there is no match' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: false)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n      end\n\n      context 'with `exact` set to `true`' do\n        it 'raises an error when there are multiple exact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: true)\n          end.to raise_error(Capybara::Ambiguous)\n        end\n\n        it 'finds a single exact match when there also are inexact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: true)\n          expect(result.text).to eq('almost singular')\n        end\n\n        it 'raises an error when there are multiple inexact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'raises an error when there is a single inexact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'raises an error if there is no match' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n      end\n    end\n\n    context 'when set to `prefer_exact`' do\n      context 'and `exact` set to `false`' do\n        it 'picks the first one when there are multiple exact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: false)\n          expect(result.text).to eq('multiple one')\n        end\n\n        it 'finds a single exact match when there also are inexact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: false)\n          expect(result.text).to eq('almost singular')\n        end\n\n        it 'picks the first one when there are multiple inexact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: false)\n          expect(result.text).to eq('almost singular but not quite')\n        end\n\n        it 'finds a single inexact match' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: false)\n          expect(result.text).to eq('almost singular but not quite')\n        end\n\n        it 'raises an error if there is no match' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: false)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n      end\n\n      context 'with `exact` set to `true`' do\n        it 'picks the first one when there are multiple exact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: true)\n          expect(result.text).to eq('multiple one')\n        end\n\n        it 'finds a single exact match when there also are inexact matches' do\n          result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: true)\n          expect(result.text).to eq('almost singular')\n        end\n\n        it 'raises an error if there are multiple inexact matches' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'raises an error if there is a single inexact match' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'raises an error if there is no match' do\n          expect do\n            @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: true)\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n      end\n    end\n\n    it 'defaults to `Capybara.match`' do\n      Capybara.match = :one\n      expect do\n        @session.find(:css, '.multiple')\n      end.to raise_error(Capybara::Ambiguous)\n      Capybara.match = :first\n      expect(@session.find(:css, '.multiple').text).to eq('multiple one')\n    end\n\n    it 'raises an error when unknown option given' do\n      expect do\n        @session.find(:css, '.singular', match: :schmoo)\n      end.to raise_error(ArgumentError)\n    end\n  end\n\n  it 'supports a custom filter block' do\n    expect(@session.find(:css, 'input', &:disabled?)[:name]).to eq('disabled_text')\n  end\n\n  context 'with spatial filters', requires: [:spatial] do\n    before do\n      @session.visit('/spatial')\n    end\n\n    let :center do\n      @session.find(:css, 'div.center')\n    end\n\n    it 'should find an element above another element' do\n      expect(@session.find(:css, 'div:not(.corner)', above: center).text).to eq('2')\n    end\n\n    it 'should find an element below another element' do\n      expect(@session.find(:css, 'div:not(.corner):not(.footer)', below: center).text).to eq('8')\n    end\n\n    it 'should find an element left of another element' do\n      expect(@session.find(:css, 'div:not(.corner)', left_of: center).text).to eq('4')\n    end\n\n    it 'should find an element right of another element' do\n      expect(@session.find(:css, 'div:not(.corner)', right_of: center).text).to eq('6')\n    end\n\n    it 'should combine spatial filters' do\n      expect(@session.find(:css, 'div', left_of: center, above: center).text).to eq('1')\n      expect(@session.find(:css, 'div', right_of: center, below: center).text).to eq('9')\n    end\n\n    it 'should find an element \"near\" another element' do\n      expect(@session.find(:css, 'div.distance', near: center).text).to eq('2')\n    end\n  end\n\n  context 'within a scope' do\n    before do\n      @session.visit('/with_scope')\n    end\n\n    it 'should find the an element using the given locator' do\n      @session.within(:xpath, \"//div[@id='for_bar']\") do\n        expect(@session.find('.//li[1]').text).to match(/With Simple HTML/)\n      end\n    end\n\n    it 'should support pseudo selectors' do\n      @session.within(:xpath, \"//div[@id='for_bar']\") do\n        expect(@session.find(:css, 'input:disabled').value).to eq('James')\n      end\n    end\n  end\n\n  it 'should raise if selector type is unknown' do\n    expect do\n      @session.find(:unknown, '//h1')\n    end.to raise_error(ArgumentError)\n  end\n\n  context 'with Capybara.test_id' do\n    it 'should not match on it when nil' do\n      Capybara.test_id = nil\n      expect(@session).not_to have_field('test_id')\n    end\n\n    it 'should work with the attribute set to `data-test-id` attribute' do\n      Capybara.test_id = 'data-test-id'\n      expect(@session.find(:field, 'test_id')[:id]).to eq 'test_field'\n    end\n\n    it 'should use a different attribute if set' do\n      Capybara.test_id = 'data-other-test-id'\n      expect(@session.find(:field, 'test_id')[:id]).to eq 'normal'\n    end\n\n    it 'should find a link with the test_id' do\n      Capybara.test_id = 'data-test-id'\n      expect(@session.find(:link, 'test-foo')[:id]).to eq 'foo'\n    end\n  end\n\n  it 'should warn if passed count options' do\n    allow(Capybara::Helpers).to receive(:warn)\n    @session.find('//h1', count: 44)\n    expect(Capybara::Helpers).to have_received(:warn).with(/'find' does not support count options/)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/first_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#first' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should find the first element using the given locator' do\n    expect(@session.first('//h1').text).to eq('This is a test')\n    expect(@session.first(\"//input[@id='test_field']\").value).to eq('monkey')\n  end\n\n  it 'should raise ElementNotFound when nothing was found' do\n    expect do\n      @session.first('//div[@id=\"nosuchthing\"]')\n    end.to raise_error Capybara::ElementNotFound\n  end\n\n  it 'should return nil when nothing was found if count options allow no results' do\n    expect(@session.first('//div[@id=\"nosuchthing\"]', minimum: 0)).to be_nil\n    expect(@session.first('//div[@id=\"nosuchthing\"]', count: 0)).to be_nil\n    expect(@session.first('//div[@id=\"nosuchthing\"]', between: (0..3))).to be_nil\n  end\n\n  it 'should accept an XPath instance' do\n    @session.visit('/form')\n    @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')\n    expect(@xpath).to be_a(XPath::Union)\n    expect(@session.first(@xpath).value).to eq('John')\n  end\n\n  it 'should raise when unused parameters are passed' do\n    expect do\n      @session.first(:css, 'h1', 'unused text')\n    end.to raise_error ArgumentError, /Unused parameters passed.*unused text/\n  end\n\n  context 'with css selectors' do\n    it 'should find the first element using the given selector' do\n      expect(@session.first(:css, 'h1').text).to eq('This is a test')\n      expect(@session.first(:css, \"input[id='test_field']\").value).to eq('monkey')\n    end\n  end\n\n  context 'with xpath selectors' do\n    it 'should find the first element using the given locator' do\n      expect(@session.first(:xpath, '//h1').text).to eq('This is a test')\n      expect(@session.first(:xpath, \"//input[@id='test_field']\").value).to eq('monkey')\n    end\n  end\n\n  context 'with css as default selector' do\n    before { Capybara.default_selector = :css }\n\n    it 'should find the first element using the given locator' do\n      expect(@session.first('h1').text).to eq('This is a test')\n      expect(@session.first(\"input[id='test_field']\").value).to eq('monkey')\n    end\n  end\n\n  context 'with visible filter' do\n    it 'should only find visible nodes when true' do\n      expect do\n        @session.first(:css, 'a#invisible', visible: true)\n      end.to raise_error Capybara::ElementNotFound\n    end\n\n    it 'should find nodes regardless of whether they are invisible when false' do\n      expect(@session.first(:css, 'a#invisible', visible: false)).to be_truthy\n      expect(@session.first(:css, 'a#invisible', visible: false, text: 'hidden link')).to be_truthy\n      expect(@session.first(:css, 'a#visible', visible: false)).to be_truthy\n    end\n\n    it 'should find nodes regardless of whether they are invisible when :all' do\n      expect(@session.first(:css, 'a#invisible', visible: :all)).to be_truthy\n      expect(@session.first(:css, 'a#invisible', visible: :all, text: 'hidden link')).to be_truthy\n      expect(@session.first(:css, 'a#visible', visible: :all)).to be_truthy\n    end\n\n    it 'should find only hidden nodes when :hidden' do\n      expect(@session.first(:css, 'a#invisible', visible: :hidden)).to be_truthy\n      expect(@session.first(:css, 'a#invisible', visible: :hidden, text: 'hidden link')).to be_truthy\n      expect do\n        @session.first(:css, 'a#invisible', visible: :hidden, text: 'not hidden link')\n      end.to raise_error Capybara::ElementNotFound\n      expect do\n        @session.first(:css, 'a#visible', visible: :hidden)\n      end.to raise_error Capybara::ElementNotFound\n    end\n\n    it 'should find only visible nodes when :visible' do\n      expect do\n        @session.first(:css, 'a#invisible', visible: :visible)\n      end.to raise_error Capybara::ElementNotFound\n      expect do\n        @session.first(:css, 'a#invisible', visible: :visible, text: 'hidden link')\n      end.to raise_error Capybara::ElementNotFound\n      expect(@session.first(:css, 'a#visible', visible: :visible)).to be_truthy\n    end\n\n    it 'should default to Capybara.ignore_hidden_elements' do\n      Capybara.ignore_hidden_elements = true\n      expect do\n        @session.first(:css, 'a#invisible')\n      end.to raise_error Capybara::ElementNotFound\n      Capybara.ignore_hidden_elements = false\n      expect(@session.first(:css, 'a#invisible')).to be_truthy\n      expect(@session.first(:css, 'a')).to be_truthy\n    end\n  end\n\n  context 'within a scope' do\n    before do\n      @session.visit('/with_scope')\n    end\n\n    it 'should find the first element using the given locator' do\n      @session.within(:xpath, \"//div[@id='for_bar']\") do\n        expect(@session.first('.//form')).to be_truthy\n      end\n    end\n  end\n\n  context 'waiting behavior', requires: [:js] do\n    before do\n      @session.visit('/with_js')\n    end\n\n    it 'should not wait if minimum: 0' do\n      @session.click_link('clickable')\n      Capybara.using_wait_time(3) do\n        start_time = Time.now\n        expect(@session.first(:css, 'a#has-been-clicked', minimum: 0)).to be_nil\n        expect(Time.now - start_time).to be < 3\n      end\n    end\n\n    it 'should wait for at least one match by default' do\n      Capybara.using_wait_time(3) do\n        @session.click_link('clickable')\n        expect(@session.first(:css, 'a#has-been-clicked')).not_to be_nil\n      end\n    end\n\n    it 'should raise an error after waiting if no match' do\n      @session.click_link('clickable')\n      Capybara.using_wait_time(3) do\n        start_time = Time.now\n        expect do\n          @session.first(:css, 'a#not-a-real-link')\n        end.to raise_error Capybara::ElementNotFound\n        expect(Time.now - start_time).to be > 3\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/frame/frame_title_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#frame_title', requires: [:frames] do\n  before do\n    @session.visit('/within_frames')\n  end\n\n  it 'should return the title in a frame' do\n    @session.within_frame('frameOne') do\n      expect(@session.driver.frame_title).to eq 'This is the title of frame one'\n    end\n  end\n\n  it 'should return the title in FrameTwo' do\n    @session.within_frame('frameTwo') do\n      expect(@session.driver.frame_title).to eq 'This is the title of frame two'\n    end\n  end\n\n  it 'should return the title in the main frame' do\n    expect(@session.driver.frame_title).to eq 'With Frames'\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/frame/frame_url_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#frame_url', requires: [:frames] do\n  before do\n    @session.visit('/within_frames')\n  end\n\n  it 'should return the url in a frame' do\n    @session.within_frame('frameOne') do\n      expect(@session.driver.frame_url).to end_with '/frame_one'\n    end\n  end\n\n  it 'should return the url in FrameTwo' do\n    @session.within_frame('frameTwo') do\n      expect(@session.driver.frame_url).to end_with '/frame_two'\n    end\n  end\n\n  it 'should return the url in the main frame' do\n    expect(@session.driver.frame_url).to end_with('/within_frames')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/frame/switch_to_frame_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#switch_to_frame', requires: [:frames] do\n  before do\n    @session.visit('/within_frames')\n  end\n\n  after do\n    # Ensure we clean up after the frame changes\n    @session.switch_to_frame(:top)\n  end\n\n  it 'should find the div in frameOne' do\n    frame = @session.find(:frame, 'frameOne')\n    @session.switch_to_frame(frame)\n    expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n  end\n\n  it 'should find the div in FrameTwo' do\n    frame = @session.find(:frame, 'frameTwo')\n    @session.switch_to_frame(frame)\n    expect(@session.find(\"//*[@id='divInFrameTwo']\").text).to eql 'This is the text of divInFrameTwo'\n  end\n\n  it 'should return to the parent frame when told to' do\n    frame = @session.find(:frame, 'frameOne')\n    @session.switch_to_frame(frame)\n    @session.switch_to_frame(:parent)\n    expect(@session.find(\"//*[@id='divInMainWindow']\").text).to eql 'This is the text for divInMainWindow'\n  end\n\n  it 'should be able to switch to nested frames' do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame frame\n    frame = @session.find(:frame, 'childFrame')\n    @session.switch_to_frame frame\n    frame = @session.find(:frame, 'grandchildFrame1')\n    @session.switch_to_frame frame\n    expect(@session).to have_selector(:css, '#divInFrameOne', text: 'This is the text of divInFrameOne')\n  end\n\n  it 'should reset scope when changing frames' do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.within(:css, '#divInMainWindow') do\n      @session.switch_to_frame(frame)\n      expect(@session.has_selector?(:css, 'iframe#childFrame')).to be true\n      @session.switch_to_frame(:parent)\n    end\n  end\n\n  it 'works if the frame is closed', requires: %i[frames js] do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame frame\n    frame = @session.find(:frame, 'childFrame')\n    @session.switch_to_frame frame\n    @session.click_link 'Close Window Now'\n    @session.switch_to_frame :parent # Go back to parentFrame\n    expect(@session).to have_selector(:css, 'body#parentBody')\n    expect(@session).not_to have_selector(:css, '#childFrame')\n    @session.switch_to_frame :parent # Go back to top\n  end\n\n  it 'works if the frame is closed with a slight delay', requires: %i[frames js] do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame frame\n    frame = @session.find(:frame, 'childFrame')\n    @session.switch_to_frame frame\n    @session.click_link 'Close Window Soon'\n    sleep 1\n    @session.switch_to_frame :parent # Go back to parentFrame\n    expect(@session).to have_selector(:css, 'body#parentBody')\n    expect(@session).not_to have_selector(:css, '#childFrame')\n    @session.switch_to_frame :parent # Go back to top\n  end\n\n  it 'can return to the top frame', requires: [:frames] do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame frame\n    frame = @session.find(:frame, 'childFrame')\n    @session.switch_to_frame frame\n    @session.switch_to_frame :top\n    expect(@session.find(\"//*[@id='divInMainWindow']\").text).to eql 'This is the text for divInMainWindow'\n  end\n\n  it \"should raise error if switching to parent unmatched inside `within` as it's nonsense\" do\n    expect do\n      frame = @session.find(:frame, 'parentFrame')\n      @session.switch_to_frame(frame)\n      @session.within(:css, '#parentBody') do\n        @session.switch_to_frame(:parent)\n      end\n    end.to raise_error(Capybara::ScopeError, \"`switch_to_frame(:parent)` cannot be called from inside a descendant frame's `within` block.\")\n  end\n\n  it \"should raise error if switching to top inside a `within` in a frame as it's nonsense\" do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame(frame)\n    @session.within(:css, '#parentBody') do\n      expect do\n        @session.switch_to_frame(:top)\n      end.to raise_error(Capybara::ScopeError, \"`switch_to_frame(:top)` cannot be called from inside a descendant frame's `within` block.\")\n    end\n  end\n\n  it \"should raise error if switching to top inside a nested `within` in a frame as it's nonsense\" do\n    frame = @session.find(:frame, 'parentFrame')\n    @session.switch_to_frame(frame)\n    @session.within(:css, '#parentBody') do\n      @session.switch_to_frame(@session.find(:frame, 'childFrame'))\n      expect do\n        @session.switch_to_frame(:top)\n      end.to raise_error(Capybara::ScopeError, \"`switch_to_frame(:top)` cannot be called from inside a descendant frame's `within` block.\")\n      @session.switch_to_frame(:parent)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/frame/within_frame_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#within_frame', requires: [:frames] do\n  before do\n    @session.visit('/within_frames')\n  end\n\n  it 'should find the div in frameOne' do\n    @session.within_frame('frameOne') do\n      expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n    end\n  end\n\n  it 'should find the div in FrameTwo' do\n    @session.within_frame('frameTwo') do\n      expect(@session.find(\"//*[@id='divInFrameTwo']\").text).to eql 'This is the text of divInFrameTwo'\n    end\n  end\n\n  it 'should find the text div in the main window after finding text in frameOne' do\n    @session.within_frame('frameOne') do\n      expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n    end\n    expect(@session.find(\"//*[@id='divInMainWindow']\").text).to eql 'This is the text for divInMainWindow'\n  end\n\n  it 'should find the text div in the main window after finding text in frameTwo' do\n    @session.within_frame('frameTwo') do\n      expect(@session.find(\"//*[@id='divInFrameTwo']\").text).to eql 'This is the text of divInFrameTwo'\n    end\n    expect(@session.find(\"//*[@id='divInMainWindow']\").text).to eql 'This is the text for divInMainWindow'\n  end\n\n  it 'should return the result of executing the block' do\n    expect(@session.within_frame('frameOne') { 'return value' }).to eql 'return value'\n  end\n\n  it 'should find the div given Element' do\n    element = @session.find(:id, 'frameOne')\n    @session.within_frame element do\n      expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n    end\n  end\n\n  it 'should find the div given selector and locator' do\n    @session.within_frame(:css, '#frameOne') do\n      expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n    end\n  end\n\n  it 'should default to the :frame selector kind when only options passed' do\n    @session.within_frame(name: 'my frame one') do\n      expect(@session.find(\"//*[@id='divInFrameOne']\").text).to eql 'This is the text of divInFrameOne'\n    end\n  end\n\n  it 'should default to the :frame selector when no options passed' do\n    container = @session.find(:css, '#divInMainWindow')\n    @session.within(container) do\n      # Ensure only one frame in scope\n      @session.within_frame do\n        expect(@session).to have_css('body#parentBody')\n      end\n    end\n    expect do\n      # Multiple frames in scope here\n      # rubocop:disable Style/Semicolon\n      @session.within_frame { ; }\n      # rubocop:enable Style/Semicolon\n    end.to raise_error Capybara::Ambiguous\n  end\n\n  it 'should find multiple nested frames' do\n    @session.within_frame 'parentFrame' do\n      @session.within_frame 'childFrame' do\n        @session.within_frame 'grandchildFrame1' do\n          # dummy\n        end\n        @session.within_frame 'grandchildFrame2' do\n          # dummy\n        end\n      end\n    end\n  end\n\n  it 'should reset scope when changing frames' do\n    @session.within(:css, '#divInMainWindow') do\n      @session.within_frame 'innerParentFrame' do\n        expect(@session.has_selector?(:css, 'iframe#childFrame')).to be true\n      end\n    end\n  end\n\n  it 'works if the frame is closed', requires: %i[frames js] do\n    @session.within_frame 'parentFrame' do\n      @session.within_frame 'childFrame' do\n        @session.click_link 'Close Window Now'\n      end\n      expect(@session).to have_selector(:css, 'body#parentBody')\n      expect(@session).not_to have_selector(:css, '#childFrame')\n    end\n  end\n\n  it 'works if the frame is closed with a slight delay', requires: %i[frames js] do\n    @session.within_frame 'parentFrame' do\n      @session.within_frame 'childFrame' do\n        @session.click_link 'Close Window Soon'\n        sleep 1\n      end\n      expect(@session).to have_selector(:css, 'body#parentBody')\n      expect(@session).not_to have_selector(:css, '#childFrame')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/go_back_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#go_back', requires: [:js] do\n  it 'should fetch a response from the driver from the previous page' do\n    @session.visit('/')\n    expect(@session).to have_content('Hello world!')\n    @session.visit('/foo')\n    expect(@session).to have_content('Another World')\n    @session.go_back\n    expect(@session).to have_content('Hello world!')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/go_forward_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#go_forward', requires: [:js] do\n  it 'should fetch a response from the driver from the previous page' do\n    @session.visit('/')\n    expect(@session).to have_content('Hello world!')\n    @session.visit('/foo')\n    expect(@session).to have_content('Another World')\n    @session.go_back\n    expect(@session).to have_content('Hello world!')\n    @session.go_forward\n    expect(@session).to have_content('Another World')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_all_selectors_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#have_all_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selectors are on the page' do\n    expect(@session).to have_all_of_selectors(:css, 'p a#foo', 'h2#h2one', 'h2#h2two')\n  end\n\n  it 'should be false if any of the given selectors are not on the page' do\n    expect do\n      expect(@session).to have_all_of_selectors(:css, 'p a#foo', 'h2#h2three', 'h2#h2one')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(@session).to have_all_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')\n    expect do\n      expect(@session).to have_all_of_selectors('p a#foo', 'h2#h2three', 'h2#h2one')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  context 'should respect scopes' do\n    it 'when used with `within`' do\n      @session.within \"//p[@id='first']\" do\n        expect(@session).to have_all_of_selectors(\".//a[@id='foo']\")\n        expect do\n          expect(@session).to have_all_of_selectors(\".//a[@id='red']\")\n        end.to raise_error RSpec::Expectations::ExpectationNotMetError\n      end\n    end\n\n    it 'when called on elements' do\n      el = @session.find \"//p[@id='first']\"\n      expect(el).to have_all_of_selectors(\".//a[@id='foo']\")\n      expect do\n        expect(el).to have_all_of_selectors(\".//a[@id='red']\")\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n    end\n  end\n\n  context 'with options' do\n    it 'should apply options to all locators' do\n      expect(@session).to have_all_of_selectors(:field, 'normal', 'additional_newline', type: :textarea)\n      expect do\n        expect(@session).to have_all_of_selectors(:field, 'normal', 'test_field', 'additional_newline', type: :textarea)\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not raise error if all the elements appear before given wait duration' do\n      Capybara.using_wait_time(0.1) do\n        @session.visit('/with_js')\n        @session.click_link('Click me')\n        expect(@session).to have_all_of_selectors(:css, 'a#clickable', 'a#has-been-clicked', '#drag', wait: 5)\n      end\n    end\n  end\n\n  it 'cannot be negated' do\n    expect do\n      expect(@session).not_to have_all_of_selectors(:css, 'p a#foo', 'h2#h2one', 'h2#h2two')\n    end.to raise_error ArgumentError\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_ancestor_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#have_ancestor' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should assert an ancestor using the given locator' do\n    el = @session.find(:css, '#ancestor1')\n    expect(el).to have_ancestor(:css, '#ancestor2')\n  end\n\n  it 'should assert an ancestor even if not parent' do\n    el = @session.find(:css, '#child')\n    expect(el).to have_ancestor(:css, '#ancestor3')\n  end\n\n  it 'should not raise an error if there are multiple matches' do\n    el = @session.find(:css, '#child')\n    expect(el).to have_ancestor(:css, 'div')\n  end\n\n  it 'should allow counts to be specified' do\n    el = @session.find(:css, '#child')\n\n    expect do\n      expect(el).to have_ancestor(:css, 'div').once\n    end.to raise_error(RSpec::Expectations::ExpectationNotMetError)\n\n    expect(el).to have_ancestor(:css, 'div').exactly(3).times\n  end\nend\n\nCapybara::SpecHelper.spec '#have_no_ancestor' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should assert no matching ancestor' do\n    el = @session.find(:css, '#ancestor1')\n    expect(el).to have_no_ancestor(:css, '#child')\n    expect(el).to have_no_ancestor(:css, '#ancestor1_sibling')\n    expect(el).not_to have_ancestor(:css, '#child')\n    expect(el).not_to have_ancestor(:css, '#ancestor1_sibling')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_any_selectors_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#have_any_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if any of the given selectors are on the page' do\n    expect(@session).to have_any_of_selectors(:css, 'p a#foo', 'h2#blah', 'h2#h2two')\n  end\n\n  it 'should be false if none of the given selectors are not on the page' do\n    expect do\n      expect(@session).to have_any_of_selectors(:css, 'span a#foo', 'h2#h2nope', 'h2#h2one_no')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(@session).to have_any_of_selectors('p a#foo', 'h2#h2two', 'a#not_on_page')\n    expect do\n      expect(@session).to have_any_of_selectors('p a#blah', 'h2#h2three')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  it 'should be negateable' do\n    expect(@session).not_to have_any_of_selectors(:css, 'span a#foo', 'h2#h2nope', 'h2#h2one_no')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_button_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_button?' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should be true if the given button is on the page' do\n    expect(@session).to have_button('med')\n    expect(@session).to have_button('crap321')\n    expect(@session).to have_button(:crap321)\n    expect(@session).to have_button('button with label element')\n    expect(@session).to have_button('button within label element')\n  end\n\n  it 'should be true for disabled buttons if disabled: true' do\n    expect(@session).to have_button('Disabled button', disabled: true)\n  end\n\n  it 'should be false if the given button is not on the page' do\n    expect(@session).not_to have_button('monkey')\n  end\n\n  it 'should be false for disabled buttons by default' do\n    expect(@session).not_to have_button('Disabled button')\n  end\n\n  it 'should be false for disabled buttons if disabled: false' do\n    expect(@session).not_to have_button('Disabled button', disabled: false)\n  end\n\n  it 'should be true for disabled buttons if disabled: :all' do\n    expect(@session).to have_button('Disabled button', disabled: :all)\n  end\n\n  it 'should be true for enabled buttons if disabled: :all' do\n    expect(@session).to have_button('med', disabled: :all)\n  end\n\n  it 'should be true for exact match if exact: true' do\n    expect(@session).to have_button('med', exact: true)\n  end\n\n  it 'can verify button type' do\n    expect(@session).to have_button('awe123', type: 'submit')\n    expect(@session).not_to have_button('awe123', type: 'reset')\n  end\n\n  it 'should be true for role=button when enable_aria_role: true' do\n    expect(@session).to have_button('ARIA button', enable_aria_role: true)\n  end\n\n  it 'should be false for a role=button within a label when enable_aria_role: true' do\n    expect(@session).not_to have_button('role=button within label', enable_aria_role: true)\n  end\n\n  it 'should be false for role=button when enable_aria_role: false' do\n    expect(@session).not_to have_button('ARIA button', enable_aria_role: false)\n  end\n\n  it 'should be false for a role=button within a label when enable_aria_role: false' do\n    expect(@session).not_to have_button('role=button within label', enable_aria_role: false)\n  end\n\n  it 'should not affect other selectors when enable_aria_role: true' do\n    expect(@session).to have_button('Click me!', enable_aria_role: true)\n  end\n\n  it 'should not affect other selectors when enable_aria_role: false' do\n    expect(@session).to have_button('Click me!', enable_aria_role: false)\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if a field has focus when focused: true' do\n      @session.send_keys(:tab)\n\n      expect(@session).to have_button('A Button', focused: true)\n    end\n\n    it 'should be true if a field does not have focus when focused: false' do\n      expect(@session).to have_button('A Button', focused: false)\n    end\n  end\n\n  it 'should raise an error if an invalid option is passed' do\n    expect do\n      expect(@session).to have_button('A Button', invalid: true)\n    end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :disabled, :name, :value, :title, :type')\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_button?' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should be true if the given button is on the page' do\n    expect(@session).not_to have_no_button('med')\n    expect(@session).not_to have_no_button('crap321')\n  end\n\n  it 'should be true for disabled buttons if disabled: true' do\n    expect(@session).not_to have_no_button('Disabled button', disabled: true)\n  end\n\n  it 'should be false if the given button is not on the page' do\n    expect(@session).to have_no_button('monkey')\n  end\n\n  it 'should be false for disabled buttons by default' do\n    expect(@session).to have_no_button('Disabled button')\n  end\n\n  it 'should be false for disabled buttons if disabled: false' do\n    expect(@session).to have_no_button('Disabled button', disabled: false)\n  end\n\n  it 'should be true for no exact match if exact: true' do\n    expect(@session).to have_no_button('button', exact: true)\n  end\n\n  it 'should be true for role=button when enable_aria_role: false' do\n    expect(@session).to have_no_button('ARIA button', enable_aria_role: false)\n  end\n\n  it 'should be true for role=button within a label when enable_aria_role: false' do\n    expect(@session).to have_no_button('role=button within label', enable_aria_role: false)\n  end\n\n  it 'should be false for role=button when enable_aria_role: true' do\n    expect(@session).not_to have_no_button('ARIA button', enable_aria_role: true)\n  end\n\n  it 'should be true for a role=button within a label when enable_aria_role: true' do\n    # label element does not associate with aria button\n    expect(@session).to have_no_button('role=button within label', enable_aria_role: true)\n  end\n\n  it 'should not affect other selectors when enable_aria_role: true' do\n    expect(@session).to have_no_button('Junk button that does not exist', enable_aria_role: true)\n  end\n\n  it 'should not affect other selectors when enable_aria_role: false' do\n    expect(@session).to have_no_button('Junk button that does not exist', enable_aria_role: false)\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if a button does not have focus when focused: true' do\n      expect(@session).to have_no_button('A Button', focused: true)\n    end\n\n    it 'should be false if a button has focus when focused: false' do\n      @session.send_keys(:tab)\n\n      expect(@session).to have_no_button('A Button', focused: false)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_css_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_css?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selector is on the page' do\n    expect(@session).to have_css('p')\n    expect(@session).to have_css('p a#foo')\n  end\n\n  it 'should warn when passed a symbol' do\n    # This was never a specifically accepted format but it has worked for a\n    # lot of versions.\n    # TODO: Remove in 4.0\n    allow(Capybara::Helpers).to receive(:warn).and_return(nil)\n    expect(@session).to have_css(:p)\n    expect(Capybara::Helpers).to have_received(:warn)\n  end\n\n  it 'should be false if the given selector is not on the page' do\n    expect(@session).not_to have_css('abbr')\n    expect(@session).not_to have_css('p a#doesnotexist')\n    expect(@session).not_to have_css('p.nosuchclass')\n  end\n\n  it 'should support :id option' do\n    expect(@session).to have_css('h2', id: 'h2one')\n    expect(@session).to have_css('h2')\n    expect(@session).to have_css('h2', id: /h2o/)\n    expect(@session).to have_css('li', id: /john|paul/)\n  end\n\n  it 'should support :class option' do\n    expect(@session).to have_css('li', class: 'guitarist')\n    expect(@session).to have_css('li', class: /guitar/)\n    expect(@session).to have_css('li', class: /guitar|drummer/)\n    expect(@session).to have_css('li', class: %w[beatle guitarist])\n    expect(@session).to have_css('li', class: /.*/)\n  end\n\n  context ':style option' do\n    it 'should support String' do\n      expect(@session).to have_css('p', style: 'line-height: 25px;')\n\n      expect do\n        expect(@session).to have_css('p', style: 'display: not_valid')\n      end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /style attribute \"display: not_valid\"/)\n    end\n\n    it 'should support Regexp' do\n      expect(@session).to have_css('p', style: /-height: 2/)\n\n      expect do\n        expect(@session).to have_css('p', style: /not_valid/)\n      end.to raise_error(RSpec::Expectations::ExpectationNotMetError, %r{style attribute matching /not_valid/})\n    end\n\n    it 'should support Hash', requires: [:css] do\n      expect(@session).to have_css('p', style: { 'line-height': '25px' })\n\n      expect do\n        expect(@session).to have_css('p', style: { 'line-height': '30px' })\n      end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /with styles \\{:\"line-height\"=>\"30px\"\\}/)\n    end\n  end\n\n  it 'should support case insensitive :class and :id options' do\n    expect(@session).to have_css('li', class: /UiTaRI/i)\n    expect(@session).to have_css('h2', id: /2ON/i)\n  end\n\n  context 'when scoped' do\n    it 'should look in the scope' do\n      @session.within \"//p[@id='first']\" do\n        expect(@session).to have_css('a#foo')\n        expect(@session).not_to have_css('a#red')\n      end\n    end\n\n    it 'should be able to generate an error message if the scope is a sibling' do\n      el = @session.find(:css, '#first')\n      @session.within el.sibling(:css, '#second') do\n        expect do\n          expect(@session).to have_css('a#not_on_page')\n        end.to raise_error(/there were no matches/)\n      end\n    end\n\n    it 'should be able to generate an error message if the scope is a sibling from XPath' do\n      el = @session.find(:css, '#first').find(:xpath, './following-sibling::*[1]') do\n        expect do\n          expect(el).to have_css('a#not_on_page')\n        end.to raise_error(/there were no matches/)\n      end\n    end\n  end\n\n  it 'should wait for content to appear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session).to have_css(\"input[type='submit'][value='New Here']\")\n  end\n\n  context 'with predicates_wait == true' do\n    it 'should wait for content to appear', requires: [:js] do\n      Capybara.predicates_wait = true\n      Capybara.default_max_wait_time = 2\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect(@session.has_css?(\"input[type='submit'][value='New Here']\")).to be true\n    end\n  end\n\n  context 'with predicates_wait == false' do\n    before do\n      Capybara.predicates_wait = false\n      Capybara.default_max_wait_time = 5\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n    end\n\n    it 'should not wait for content to appear', requires: [:js] do\n      expect(@session.has_css?(\"input[type='submit'][value='New Here']\")).to be false\n    end\n\n    it 'should should the default wait time if true is passed for :wait', requires: [:js] do\n      expect(@session.has_css?(\"input[type='submit'][value='New Here']\", wait: true)).to be true\n    end\n  end\n\n  context 'with between' do\n    it 'should be true if the content occurs within the range given' do\n      expect(@session).to have_css('p', between: 1..4)\n      expect(@session).to have_css('p a#foo', between: 1..3)\n      expect(@session).to have_css('p a.doesnotexist', between: 0..8)\n    end\n\n    it 'should be false if the content occurs more or fewer times than range' do\n      expect(@session).not_to have_css('p', between: 6..11)\n      expect(@session).not_to have_css('p a#foo', between: 4..7)\n      expect(@session).not_to have_css('p a.doesnotexist', between: 3..8)\n    end\n  end\n\n  context 'with count' do\n    it 'should be true if the content occurs the given number of times' do\n      expect(@session).to have_css('p', count: 3)\n      expect(@session).to have_css('p').exactly(3).times\n      expect(@session).to have_css('p a#foo', count: 1)\n      expect(@session).to have_css('p a#foo').once\n      expect(@session).to have_css('p a.doesnotexist', count: 0)\n      expect(@session).to have_css('li', class: /guitar|drummer/, count: 4)\n      expect(@session).to have_css('li', id: /john|paul/, class: /guitar|drummer/, count: 2)\n      expect(@session).to have_css('li', class: %w[beatle guitarist], count: 2)\n      expect(@session).to have_css('p', style: 'line-height: 25px;', count: 1)\n      expect(@session).to have_css('p', style: /-height: 2/, count: 1)\n    end\n\n    it 'should be true if the content occurs the given number of times in CSS processing drivers', requires: [:css] do\n      expect(@session).to have_css('p', style: { 'line-height': '25px' }, count: 1)\n    end\n\n    it 'should be false if the content occurs a different number of times than the given' do\n      expect(@session).not_to have_css('p', count: 6)\n      expect(@session).not_to have_css('p').exactly(5).times\n      expect(@session).not_to have_css('p a#foo', count: 2)\n      expect(@session).not_to have_css('p a.doesnotexist', count: 1)\n    end\n\n    it 'should coerce count to an integer' do\n      expect(@session).to have_css('p', count: '3')\n      expect(@session).to have_css('p a#foo', count: '1')\n    end\n  end\n\n  context 'with maximum' do\n    it 'should be true when content occurs same or fewer times than given' do\n      expect(@session).to have_css('h2.head', maximum: 5) # edge case\n      expect(@session).to have_css('h2', maximum: 10)\n      expect(@session).to have_css('h2').at_most(10).times\n      expect(@session).to have_css('p a.doesnotexist', maximum: 1)\n      expect(@session).to have_css('p a.doesnotexist', maximum: 0)\n    end\n\n    it 'should be false when content occurs more times than given' do\n      # expect(@session).not_to have_css('h2.head', maximum: 4) # edge case\n      # expect(@session).not_to have_css('h2', maximum: 3)\n      expect(@session).not_to have_css('h2').at_most(3).times\n      # expect(@session).not_to have_css('p', maximum: 1)\n    end\n\n    it 'should coerce maximum to an integer' do\n      expect(@session).to have_css('h2.head', maximum: '5') # edge case\n      expect(@session).to have_css('h2', maximum: '10')\n    end\n  end\n\n  context 'with minimum' do\n    it 'should be true when content occurs same or more times than given' do\n      expect(@session).to have_css('h2.head', minimum: 5) # edge case\n      expect(@session).to have_css('h2', minimum: 3)\n      expect(@session).to have_css('h2').at_least(2).times\n      expect(@session).to have_css('p a.doesnotexist', minimum: 0)\n    end\n\n    it 'should be false when content occurs fewer times than given' do\n      expect(@session).not_to have_css('h2.head', minimum: 6) # edge case\n      expect(@session).not_to have_css('h2', minimum: 8)\n      expect(@session).not_to have_css('h2').at_least(8).times\n      expect(@session).not_to have_css('p', minimum: 10)\n      expect(@session).not_to have_css('p a.doesnotexist', minimum: 1)\n    end\n\n    it 'should coerce minimum to an integer' do\n      expect(@session).to have_css('h2.head', minimum: '5') # edge case\n      expect(@session).to have_css('h2', minimum: '3')\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      expect(@session).to have_css('p a', text: 'Redirect', count: 1)\n      expect(@session).not_to have_css('p a', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is not matched' do\n      expect(@session).to have_css('p a', text: /re[dab]i/i, count: 1)\n      expect(@session).not_to have_css('p a', text: /Red$/)\n    end\n  end\n\n  context 'with spatial requirements', requires: [:spatial] do\n    before do\n      @session.visit('/spatial')\n    end\n\n    let :center do\n      @session.find(:css, '.center')\n    end\n\n    it 'accepts spatial options' do\n      expect(@session).to have_css('div', above: center).thrice\n      expect(@session).to have_css('div', above: center, right_of: center).once\n    end\n\n    it 'supports spatial sugar' do\n      expect(@session).to have_css('div').left_of(center).thrice\n      expect(@session).to have_css('div').below(center).right_of(center).once\n      expect(@session).to have_css('div').near(center).exactly(8).times\n    end\n  end\n\n  it 'should allow escapes in the CSS selector' do\n    expect(@session).to have_css('p[data-random=\"abc\\\\\\\\def\"]')\n    expect(@session).to have_css(\"p[data-random='#{Capybara::Selector::CSS.escape('abc\\def')}']\")\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_css?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given selector is on the page' do\n    expect(@session).not_to have_no_css('p')\n    expect(@session).not_to have_no_css('p a#foo')\n  end\n\n  it 'should be true if the given selector is not on the page' do\n    expect(@session).to have_no_css('abbr')\n    expect(@session).to have_no_css('p a#doesnotexist')\n    expect(@session).to have_no_css('p.nosuchclass')\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect(@session).not_to have_no_css('a#foo')\n      expect(@session).to have_no_css('a#red')\n    end\n  end\n\n  it 'should wait for content to disappear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session).to have_no_css('p#change')\n  end\n\n  context 'with between' do\n    it 'should be false if the content occurs within the range given' do\n      expect(@session).not_to have_no_css('p', between: 1..4)\n      expect(@session).not_to have_no_css('p a#foo', between: 1..3)\n      expect(@session).not_to have_no_css('p a.doesnotexist', between: 0..2)\n    end\n\n    it 'should be true if the content occurs more or fewer times than range' do\n      expect(@session).to have_no_css('p', between: 6..11)\n      expect(@session).to have_no_css('p a#foo', between: 4..7)\n      expect(@session).to have_no_css('p a.doesnotexist', between: 3..8)\n    end\n  end\n\n  context 'with count' do\n    it 'should be false if the content is on the page the given number of times' do\n      expect(@session).not_to have_no_css('p', count: 3)\n      expect(@session).not_to have_no_css('p a#foo', count: 1)\n      expect(@session).not_to have_no_css('p a.doesnotexist', count: 0)\n    end\n\n    it 'should be true if the content is on the page the given number of times' do\n      expect(@session).to have_no_css('p', count: 6)\n      expect(@session).to have_no_css('p a#foo', count: 2)\n      expect(@session).to have_no_css('p a.doesnotexist', count: 1)\n    end\n\n    it 'should coerce count to an integer' do\n      expect(@session).not_to have_no_css('p', count: '3')\n      expect(@session).not_to have_no_css('p a#foo', count: '1')\n    end\n  end\n\n  context 'with maximum' do\n    it 'should be false when content occurs same or fewer times than given' do\n      expect(@session).not_to have_no_css('h2.head', maximum: 5) # edge case\n      expect(@session).not_to have_no_css('h2', maximum: 10)\n      expect(@session).not_to have_no_css('p a.doesnotexist', maximum: 0)\n    end\n\n    it 'should be true when content occurs more times than given' do\n      expect(@session).to have_no_css('h2.head', maximum: 4) # edge case\n      expect(@session).to have_no_css('h2', maximum: 3)\n      expect(@session).to have_no_css('p', maximum: 1)\n    end\n\n    it 'should coerce maximum to an integer' do\n      expect(@session).not_to have_no_css('h2.head', maximum: '5') # edge case\n      expect(@session).not_to have_no_css('h2', maximum: '10')\n    end\n  end\n\n  context 'with minimum' do\n    it 'should be false when content occurs same or more times than given' do\n      expect(@session).not_to have_no_css('h2.head', minimum: 5) # edge case\n      expect(@session).not_to have_no_css('h2', minimum: 3)\n      expect(@session).not_to have_no_css('p a.doesnotexist', minimum: 0)\n    end\n\n    it 'should be true when content occurs fewer times than given' do\n      expect(@session).to have_no_css('h2.head', minimum: 6) # edge case\n      expect(@session).to have_no_css('h2', minimum: 8)\n      expect(@session).to have_no_css('p', minimum: 15)\n      expect(@session).to have_no_css('p a.doesnotexist', minimum: 1)\n    end\n\n    it 'should coerce minimum to an integer' do\n      expect(@session).not_to have_no_css('h2.head', minimum: '4') # edge case\n      expect(@session).not_to have_no_css('h2', minimum: '3')\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      expect(@session).not_to have_no_css('p a', text: 'Redirect', count: 1)\n      expect(@session).to have_no_css('p a', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is not matched' do\n      expect(@session).not_to have_no_css('p a', text: /re[dab]i/i, count: 1)\n      expect(@session).to have_no_css('p a', text: /Red$/)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_current_path_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_current_path?' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should be true if the page has the given current path' do\n    expect(@session).to have_current_path('/with_js')\n  end\n\n  it 'should allow regexp matches' do\n    expect(@session).to have_current_path(/w[a-z]{3}_js/)\n    expect(@session).not_to have_current_path(/monkey/)\n  end\n\n  it 'should not raise an error when non-http' do\n    @session.reset_session!\n    expect(@session.has_current_path?(/monkey/)).to be false\n    expect(@session.has_current_path?('/with_js')).to be false\n  end\n\n  it 'should handle non-escaped query options' do\n    @session.click_link('Non-escaped query options')\n    expect(@session).to have_current_path('/with_html?options[]=things')\n  end\n\n  it 'should handle escaped query options' do\n    @session.click_link('Escaped query options')\n    expect(@session).to have_current_path('/with_html?options%5B%5D=things')\n  end\n\n  it 'should wait for current_path', requires: [:js] do\n    @session.click_link('Change page')\n    expect(@session).to have_current_path('/with_html', wait: 3)\n  end\n\n  it 'should be false if the page has not the given current_path' do\n    expect(@session).not_to have_current_path('/with_html')\n  end\n\n  it 'should check query options' do\n    @session.visit('/with_js?test=test')\n    expect(@session).to have_current_path('/with_js?test=test')\n  end\n\n  it 'should compare the full url if url: true is used' do\n    expect(@session).to have_current_path(%r{\\Ahttp://[^/]*/with_js\\Z}, url: true)\n    domain_port = if @session.respond_to?(:server) && @session.server\n      \"#{@session.server.host}:#{@session.server.port}\"\n    else\n      'www.example.com'\n    end\n    expect(@session).to have_current_path(\"http://#{domain_port}/with_js\", url: true)\n  end\n\n  it 'should not compare the full url if url: true is not passed' do\n    expect(@session).to have_current_path(%r{^/with_js\\Z})\n    expect(@session).to have_current_path('/with_js')\n  end\n\n  it 'should not compare the full url if url: false is passed' do\n    expect(@session).to have_current_path(%r{^/with_js\\Z}, url: false)\n    expect(@session).to have_current_path('/with_js', url: false)\n  end\n\n  it 'should default to full url if value is a url' do\n    url = @session.current_url\n    expect(url).to match(/with_js$/)\n    expect(@session).to have_current_path(url)\n    expect(@session).not_to have_current_path('http://www.not_example.com/with_js')\n  end\n\n  it 'should ignore the query' do\n    @session.visit('/with_js?test=test')\n    expect(@session).to have_current_path('/with_js?test=test')\n    expect(@session).to have_current_path('/with_js', ignore_query: true)\n    uri = Addressable::URI.parse(@session.current_url)\n    uri.query = nil\n    expect(@session).to have_current_path(uri.to_s, ignore_query: true)\n  end\n\n  it 'should not raise an exception if the current_url is nil' do\n    allow(@session).to receive(:current_url).and_return(nil)\n    allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page\n\n    # Without ignore_query option\n    expect do\n      expect(@session).to have_current_path(nil)\n    end.not_to raise_exception\n\n    # With ignore_query option\n    expect do\n      expect(@session).to have_current_path(nil, ignore_query: true)\n    end.not_to raise_exception\n  end\n\n  it 'should accept a filter block that receives Addressable::URL' do\n    @session.visit('/with_js?a=3&b=defgh')\n    expect(@session).to have_current_path('/with_js', ignore_query: true) { |url|\n      url.query_values.keys == %w[a b]\n    }\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_current_path?' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should be false if the page has the given current_path' do\n    expect(@session).not_to have_no_current_path('/with_js')\n  end\n\n  it 'should allow regexp matches' do\n    expect(@session).not_to have_no_current_path(/w[a-z]{3}_js/)\n    expect(@session).to have_no_current_path(/monkey/)\n  end\n\n  it 'should wait for current_path to disappear', requires: [:js] do\n    Capybara.using_wait_time(3) do\n      @session.click_link('Change page')\n      expect(@session).to have_no_current_path('/with_js')\n    end\n  end\n\n  it 'should be true if the page has not the given current_path' do\n    expect(@session).to have_no_current_path('/with_html')\n  end\n\n  it 'should not raise an exception if the current_url is nil' do\n    allow(@session).to receive(:current_url).and_return(nil)\n    allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page\n\n    # Without ignore_query option\n    expect do\n      expect(@session).not_to have_current_path('/with_js')\n    end.not_to raise_exception\n\n    # With ignore_query option\n    expect do\n      expect(@session).not_to have_current_path('/with_js', ignore_query: true)\n    end.not_to raise_exception\n  end\n\n  it 'should accept a filter block that receives Addressable::URL' do\n    expect(@session).to have_no_current_path('/with_js', ignore_query: true) { |url|\n      !url.query.nil?\n    }\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_element_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_element?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given element is on the page' do\n    expect(@session).to have_element('a', id: 'foo')\n    expect(@session).to have_element('a', text: 'A link', href: '/with_simple_html')\n    # Should `text` actually accept a symbol?\n    # expect(@session).to have_element('a', text: :'A link', href: :'/with_simple_html')\n    expect(@session).to have_element('a', text: 'A link', href: %r{/with_simple_html})\n    expect(@session).to have_element('a', text: 'labore', target: '_self')\n  end\n\n  it 'should be false if the given element is not on the page' do\n    expect(@session).not_to have_element('a', text: 'monkey')\n    expect(@session).not_to have_element('a', text: 'A link', href: '/nonexistent-href')\n    expect(@session).not_to have_element('a', text: 'A link', href: /nonexistent/)\n    expect(@session).not_to have_element('a', text: 'labore', target: '_blank')\n  end\n\n  it 'should notify if an invalid locator is specified' do\n    allow(Capybara::Helpers).to receive(:warn).and_return(nil)\n    @session.has_element?(@session)\n    expect(Capybara::Helpers).to have_received(:warn).with(/Called from: .+/)\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_element?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given element is on the page' do\n    expect(@session).not_to have_no_element('a', id: 'foo')\n    expect(@session).not_to have_no_element('a', text: 'A link', href: '/with_simple_html')\n    expect(@session).not_to have_no_element('a', text: 'labore', target: '_self')\n  end\n\n  it 'should be true if the given element is not on the page' do\n    expect(@session).to have_no_element('a', text: 'monkey')\n    expect(@session).to have_no_element('a', text: 'A link', href: '/nonexistent-href')\n    expect(@session).to have_no_element('a', text: 'A link', href: %r{/nonexistent-href})\n    expect(@session).to have_no_element('a', text: 'labore', target: '_blank')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_field_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_field' do\n  before { @session.visit('/form') }\n\n  it 'should be true if the field is on the page' do\n    expect(@session).to have_field('Dog')\n    expect(@session).to have_field('form_description')\n    expect(@session).to have_field('Region')\n    expect(@session).to have_field(:Region)\n  end\n\n  it 'should be false if the field is not on the page' do\n    expect(@session).not_to have_field('Monkey')\n  end\n\n  context 'with value' do\n    it 'should be true if a field with the given value is on the page' do\n      expect(@session).to have_field('First Name', with: 'John')\n      expect(@session).to have_field('First Name', with: /^Joh/)\n      expect(@session).to have_field('Phone', with: '+1 555 7021')\n      expect(@session).to have_field('Street', with: 'Sesame street 66')\n      expect(@session).to have_field('Description', with: 'Descriptive text goes here')\n    end\n\n    it 'should be false if the given field is not on the page' do\n      expect(@session).not_to have_field('First Name', with: 'Peter')\n      expect(@session).not_to have_field('First Name', with: /eter$/)\n      expect(@session).not_to have_field('Wrong Name', with: 'John')\n      expect(@session).not_to have_field('Description', with: 'Monkey')\n    end\n\n    it 'should be true after the field has been filled in with the given value' do\n      @session.fill_in('First Name', with: 'Jonas')\n      expect(@session).to have_field('First Name', with: 'Jonas')\n      expect(@session).to have_field('First Name', with: /ona/)\n    end\n\n    it 'should be false after the field has been filled in with a different value' do\n      @session.fill_in('First Name', with: 'Jonas')\n      expect(@session).not_to have_field('First Name', with: 'John')\n      expect(@session).not_to have_field('First Name', with: /John|Paul|George|Ringo/)\n    end\n\n    it 'should output filter errors if only one element matched the selector but failed the filters' do\n      @session.fill_in('First Name', with: 'Thomas')\n      expect do\n        expect(@session).to have_field('First Name', with: 'Jonas')\n      end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected value to be \"Jonas\" but was \"Thomas\"/)\n\n      # native boolean node filter\n      expect do\n        expect(@session).to have_field('First Name', readonly: true)\n      end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected readonly true but it wasn't/)\n\n      # inherited boolean node filter\n      expect do\n        expect(@session).to have_field('form_pets_cat', checked: true)\n      end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected checked true but it wasn't/)\n    end\n  end\n\n  context 'with validation message', requires: [:html_validation] do\n    it 'should accept a regexp' do\n      @session.fill_in('form_zipcode', with: '1234')\n      expect(@session).to have_field('form_zipcode', validation_message: /match the requested format/)\n      expect(@session).not_to have_field('form_zipcode', validation_message: /random/)\n    end\n\n    it 'should accept a string' do\n      @session.fill_in('form_zipcode', with: '1234')\n      expect(@session).to have_field('form_zipcode', validation_message: 'Please match the requested format.')\n      expect(@session).not_to have_field('form_zipcode', validation_message: 'match the requested format.')\n      @session.fill_in('form_zipcode', with: '12345')\n      expect(@session).to have_field('form_zipcode', validation_message: '')\n    end\n  end\n\n  context 'with type' do\n    it 'should be true if a field with the given type is on the page' do\n      expect(@session).to have_field('First Name', type: 'text')\n      expect(@session).to have_field('Html5 Email', type: 'email')\n      expect(@session).to have_field('Html5 Multiple Email', type: 'email')\n      expect(@session).to have_field('Html5 Tel', type: 'tel')\n      expect(@session).to have_field('Description', type: 'textarea')\n      expect(@session).to have_field('Languages', type: 'select')\n    end\n\n    it 'should be false if the given field is not on the page' do\n      expect(@session).not_to have_field('First Name', type: 'textarea')\n      expect(@session).not_to have_field('Html5 Email', type: 'tel')\n      expect(@session).not_to have_field('Html5 Multiple Email', type: 'tel')\n      expect(@session).not_to have_field('Description', type: '')\n      expect(@session).not_to have_field('Description', type: 'email')\n      expect(@session).not_to have_field('Languages', type: 'textarea')\n    end\n\n    it 'it can find type=\"hidden\" elements if explicity specified' do\n      expect(@session).to have_field('form[data]', with: 'TWTW', type: 'hidden')\n    end\n  end\n\n  context 'with multiple' do\n    it 'should be true if a field with the multiple attribute is on the page' do\n      expect(@session).to have_field('Html5 Multiple Email', multiple: true)\n    end\n\n    it 'should be false if a field without the multiple attribute is not on the page' do\n      expect(@session).not_to have_field('Html5 Multiple Email', multiple: false)\n    end\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if a field has focus' do\n      2.times { @session.send_keys(:tab) }\n\n      expect(@session).to have_field('An Input', focused: true)\n    end\n\n    it 'should be false if a field does not have focus' do\n      expect(@session).to have_field('An Input', focused: false)\n    end\n  end\n\n  context 'with valid', requires: [:js] do\n    it 'should be true if field is valid' do\n      @session.fill_in 'required', with: 'something'\n      @session.fill_in 'length', with: 'abcd'\n\n      expect(@session).to have_field('required', valid: true)\n      expect(@session).to have_field('length', valid: true)\n    end\n\n    it 'should be false if field is invalid' do\n      expect(@session).not_to have_field('required', valid: true)\n      expect(@session).to have_field('required', valid: false)\n\n      @session.fill_in 'length', with: 'abc'\n      expect(@session).not_to have_field('length', valid: true)\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_field' do\n  before { @session.visit('/form') }\n\n  it 'should be false if the field is on the page' do\n    expect(@session).not_to have_no_field('Dog')\n    expect(@session).not_to have_no_field('form_description')\n    expect(@session).not_to have_no_field('Region')\n  end\n\n  it 'should be true if the field is not on the page' do\n    expect(@session).to have_no_field('Monkey')\n  end\n\n  context 'with value' do\n    it 'should be false if a field with the given value is on the page' do\n      expect(@session).not_to have_no_field('First Name', with: 'John')\n      expect(@session).not_to have_no_field('Phone', with: '+1 555 7021')\n      expect(@session).not_to have_no_field('Street', with: 'Sesame street 66')\n      expect(@session).not_to have_no_field('Description', with: 'Descriptive text goes here')\n    end\n\n    it 'should be true if the given field is not on the page' do\n      expect(@session).to have_no_field('First Name', with: 'Peter')\n      expect(@session).to have_no_field('Wrong Name', with: 'John')\n      expect(@session).to have_no_field('Description', with: 'Monkey')\n    end\n\n    it 'should be false after the field has been filled in with the given value' do\n      @session.fill_in('First Name', with: 'Jonas')\n      expect(@session).not_to have_no_field('First Name', with: 'Jonas')\n    end\n\n    it 'should be true after the field has been filled in with a different value' do\n      @session.fill_in('First Name', with: 'Jonas')\n      expect(@session).to have_no_field('First Name', with: 'John')\n    end\n  end\n\n  context 'with type' do\n    it 'should be false if a field with the given type is on the page' do\n      expect(@session).not_to have_no_field('First Name', type: 'text')\n      expect(@session).not_to have_no_field('Html5 Email', type: 'email')\n      expect(@session).not_to have_no_field('Html5 Tel', type: 'tel')\n      expect(@session).not_to have_no_field('Description', type: 'textarea')\n      expect(@session).not_to have_no_field('Languages', type: 'select')\n    end\n\n    it 'should be true if the given field is not on the page' do\n      expect(@session).to have_no_field('First Name', type: 'textarea')\n      expect(@session).to have_no_field('Html5 Email', type: 'tel')\n      expect(@session).to have_no_field('Description', type: '')\n      expect(@session).to have_no_field('Description', type: 'email')\n      expect(@session).to have_no_field('Languages', type: 'textarea')\n    end\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if a field does not have focus when focused: true' do\n      expect(@session).to have_no_field('An Input', focused: true)\n    end\n\n    it 'should be false if a field has focus when focused: true' do\n      2.times { @session.send_keys(:tab) }\n\n      expect(@session).not_to have_no_field('An Input', focused: true)\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#has_checked_field?' do\n  before { @session.visit('/form') }\n\n  it 'should be true if a checked field is on the page' do\n    expect(@session).to have_checked_field('gender_female')\n    expect(@session).to have_checked_field('Hamster')\n  end\n\n  it 'should be true for disabled checkboxes if disabled: true' do\n    expect(@session).to have_checked_field('Disabled Checkbox', disabled: true)\n  end\n\n  it 'should be false if an unchecked field is on the page' do\n    expect(@session).not_to have_checked_field('form_pets_cat')\n    expect(@session).not_to have_checked_field('Male')\n  end\n\n  it 'should be false if no field is on the page' do\n    expect(@session).not_to have_checked_field('Does Not Exist')\n  end\n\n  it 'should be false for disabled checkboxes by default' do\n    expect(@session).not_to have_checked_field('Disabled Checkbox')\n  end\n\n  it 'should be false for disabled checkboxes if disabled: false' do\n    expect(@session).not_to have_checked_field('Disabled Checkbox', disabled: false)\n  end\n\n  it 'should be true for disabled checkboxes if disabled: :all' do\n    expect(@session).to have_checked_field('Disabled Checkbox', disabled: :all)\n  end\n\n  it 'should be true for enabled checkboxes if disabled: :all' do\n    expect(@session).to have_checked_field('gender_female', disabled: :all)\n  end\n\n  it 'should be true after an unchecked checkbox is checked' do\n    @session.check('form_pets_cat')\n    expect(@session).to have_checked_field('form_pets_cat')\n  end\n\n  it 'should be false after a checked checkbox is unchecked' do\n    @session.uncheck('form_pets_dog')\n    expect(@session).not_to have_checked_field('form_pets_dog')\n  end\n\n  it 'should be true after an unchecked radio button is chosen' do\n    @session.choose('gender_male')\n    expect(@session).to have_checked_field('gender_male')\n  end\n\n  it 'should be false after another radio button in the group is chosen' do\n    @session.choose('gender_male')\n    expect(@session).not_to have_checked_field('gender_female')\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_checked_field?' do\n  before { @session.visit('/form') }\n\n  it 'should be false if a checked field is on the page' do\n    expect(@session).not_to have_no_checked_field('gender_female')\n    expect(@session).not_to have_no_checked_field('Hamster')\n  end\n\n  it 'should be false for disabled checkboxes if disabled: true' do\n    expect(@session).not_to have_no_checked_field('Disabled Checkbox', disabled: true)\n  end\n\n  it 'should be true if an unchecked field is on the page' do\n    expect(@session).to have_no_checked_field('form_pets_cat')\n    expect(@session).to have_no_checked_field('Male')\n  end\n\n  it 'should be true if no field is on the page' do\n    expect(@session).to have_no_checked_field('Does Not Exist')\n  end\n\n  it 'should be true for disabled checkboxes by default' do\n    expect(@session).to have_no_checked_field('Disabled Checkbox')\n  end\n\n  it 'should be true for disabled checkboxes if disabled: false' do\n    expect(@session).to have_no_checked_field('Disabled Checkbox', disabled: false)\n  end\nend\n\nCapybara::SpecHelper.spec '#has_unchecked_field?' do\n  before { @session.visit('/form') }\n\n  it 'should be false if a checked field is on the page' do\n    expect(@session).not_to have_unchecked_field('gender_female')\n    expect(@session).not_to have_unchecked_field('Hamster')\n  end\n\n  it 'should be true if an unchecked field is on the page' do\n    expect(@session).to have_unchecked_field('form_pets_cat')\n    expect(@session).to have_unchecked_field('Male')\n  end\n\n  it 'should be true for disabled unchecked fields if disabled: true' do\n    expect(@session).to have_unchecked_field('Disabled Unchecked Checkbox', disabled: true)\n  end\n\n  it 'should be false if no field is on the page' do\n    expect(@session).not_to have_unchecked_field('Does Not Exist')\n  end\n\n  it 'should be false for disabled unchecked fields by default' do\n    expect(@session).not_to have_unchecked_field('Disabled Unchecked Checkbox')\n  end\n\n  it 'should be false for disabled unchecked fields if disabled: false' do\n    expect(@session).not_to have_unchecked_field('Disabled Unchecked Checkbox', disabled: false)\n  end\n\n  it 'should be false after an unchecked checkbox is checked' do\n    @session.check('form_pets_cat')\n    expect(@session).not_to have_unchecked_field('form_pets_cat')\n  end\n\n  it 'should be true after a checked checkbox is unchecked' do\n    @session.uncheck('form_pets_dog')\n    expect(@session).to have_unchecked_field('form_pets_dog')\n  end\n\n  it 'should be false after an unchecked radio button is chosen' do\n    @session.choose('gender_male')\n    expect(@session).not_to have_unchecked_field('gender_male')\n  end\n\n  it 'should be true after another radio button in the group is chosen' do\n    @session.choose('gender_male')\n    expect(@session).to have_unchecked_field('gender_female')\n  end\n\n  it 'should support locator-less usage' do\n    expect(@session.has_unchecked_field?(disabled: true, id: 'form_disabled_unchecked_checkbox')).to be true\n    expect(@session).to have_unchecked_field(disabled: true, id: 'form_disabled_unchecked_checkbox')\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_unchecked_field?' do\n  before { @session.visit('/form') }\n\n  it 'should be true if a checked field is on the page' do\n    expect(@session).to have_no_unchecked_field('gender_female')\n    expect(@session).to have_no_unchecked_field('Hamster')\n  end\n\n  it 'should be false if an unchecked field is on the page' do\n    expect(@session).not_to have_no_unchecked_field('form_pets_cat')\n    expect(@session).not_to have_no_unchecked_field('Male')\n  end\n\n  it 'should be false for disabled unchecked fields if disabled: true' do\n    expect(@session).not_to have_no_unchecked_field('Disabled Unchecked Checkbox', disabled: true)\n  end\n\n  it 'should be true if no field is on the page' do\n    expect(@session).to have_no_unchecked_field('Does Not Exist')\n  end\n\n  it 'should be true for disabled unchecked fields by default' do\n    expect(@session).to have_no_unchecked_field('Disabled Unchecked Checkbox')\n  end\n\n  it 'should be true for disabled unchecked fields if disabled: false' do\n    expect(@session).to have_no_unchecked_field('Disabled Unchecked Checkbox', disabled: false)\n  end\n\n  it 'should support locator-less usage' do\n    expect(@session.has_no_unchecked_field?(disabled: false, id: 'form_disabled_unchecked_checkbox')).to be true\n    expect(@session).to have_no_unchecked_field(disabled: false, id: 'form_disabled_unchecked_checkbox')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_link_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_link?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given link is on the page' do\n    expect(@session).to have_link('foo')\n    expect(@session).to have_link('awesome title')\n    expect(@session).to have_link('A link', href: '/with_simple_html')\n    expect(@session).to have_link(:'A link', href: :'/with_simple_html')\n    expect(@session).to have_link('A link', href: %r{/with_simple_html})\n    expect(@session).to have_link('labore', target: '_self')\n  end\n\n  it 'should be false if the given link is not on the page' do\n    expect(@session).not_to have_link('monkey')\n    expect(@session).not_to have_link('A link', href: '/nonexistent-href')\n    expect(@session).not_to have_link('A link', href: /nonexistent/)\n    expect(@session).not_to have_link('labore', target: '_blank')\n  end\n\n  it 'should notify if an invalid locator is specified' do\n    allow(Capybara::Helpers).to receive(:warn).and_return(nil)\n    @session.has_link?(@session)\n    expect(Capybara::Helpers).to have_received(:warn).with(/Called from: .+/)\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if the given link is on the page and has focus' do\n      @session.send_keys(:tab)\n\n      expect(@session).to have_link('labore', focused: true)\n    end\n\n    it 'should be false if the given link is on the page and does not have focus' do\n      expect(@session).to have_link('labore', focused: false)\n    end\n  end\n\n  it 'should raise an error if an invalid option is passed' do\n    expect do\n      expect(@session).to have_link('labore', invalid: true)\n    end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :href, :alt, :title, :target, :download')\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_link?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given link is on the page' do\n    expect(@session).not_to have_no_link('foo')\n    expect(@session).not_to have_no_link('awesome title')\n    expect(@session).not_to have_no_link('A link', href: '/with_simple_html')\n    expect(@session).not_to have_no_link('labore', target: '_self')\n  end\n\n  it 'should be true if the given link is not on the page' do\n    expect(@session).to have_no_link('monkey')\n    expect(@session).to have_no_link('A link', href: '/nonexistent-href')\n    expect(@session).to have_no_link('A link', href: %r{/nonexistent-href})\n    expect(@session).to have_no_link('labore', target: '_blank')\n  end\n\n  context 'with focused:', requires: [:active_element] do\n    it 'should be true if the given link is on the page and has focus' do\n      expect(@session).to have_no_link('labore', focused: true)\n    end\n\n    it 'should be false if the given link is on the page and does not have focus' do\n      @session.send_keys(:tab)\n\n      expect(@session).to have_no_link('labore', focused: false)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_none_selectors_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#have_none_of_selectors' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if any of the given locators are on the page' do\n    expect do\n      expect(@session).to have_none_of_selectors(:xpath, '//p', '//a')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n    expect do\n      expect(@session).to have_none_of_selectors(:css, 'p a#foo')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  it 'should be true if none of the given locators are on the page' do\n    expect(@session).to have_none_of_selectors(:xpath, '//abbr', '//td')\n    expect(@session).to have_none_of_selectors(:css, 'p a#doesnotexist', 'abbr')\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(@session).to have_none_of_selectors('p a#doesnotexist', 'abbr')\n    expect do\n      expect(@session).to have_none_of_selectors('abbr', 'p a#foo')\n    end.to raise_error RSpec::Expectations::ExpectationNotMetError\n  end\n\n  context 'should respect scopes' do\n    it 'when used with `within`' do\n      @session.within \"//p[@id='first']\" do\n        expect do\n          expect(@session).to have_none_of_selectors(\".//a[@id='foo']\")\n        end.to raise_error RSpec::Expectations::ExpectationNotMetError\n        expect(@session).to have_none_of_selectors(\".//a[@id='red']\")\n      end\n    end\n\n    it 'when called on an element' do\n      el = @session.find \"//p[@id='first']\"\n      expect do\n        expect(el).to have_none_of_selectors(\".//a[@id='foo']\")\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n      expect(el).to have_none_of_selectors(\".//a[@id='red']\")\n    end\n  end\n\n  context 'with options' do\n    it 'should apply the options to all locators' do\n      expect do\n        expect(@session).to have_none_of_selectors('//p//a', text: 'Redirect')\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n      expect(@session).to have_none_of_selectors('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is matched' do\n      expect do\n        expect(@session).to have_none_of_selectors('//p//a', text: /re[dab]i/i, count: 1)\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n      expect(@session).to have_none_of_selectors('//p//a', text: /Red$/)\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not find elements if they appear after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect(@session).to have_none_of_selectors(:css, '#new_field', 'a#has-been-clicked', wait: 0.1)\n    end\n  end\n\n  it 'cannot be negated' do\n    expect do\n      expect(@session).not_to have_none_of_selectors(:css, 'p a#foo', 'h2#h2one', 'h2#h2two')\n    end.to raise_error ArgumentError\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_select_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_select?' do\n  before { @session.visit('/form') }\n\n  it 'should be true if the field is on the page' do\n    expect(@session).to have_select('Locale')\n    expect(@session).to have_select('form_region')\n    expect(@session).to have_select('Languages')\n    expect(@session).to have_select(:Languages)\n  end\n\n  it 'should be false if the field is not on the page' do\n    expect(@session).not_to have_select('Monkey')\n  end\n\n  context 'with selected value' do\n    it 'should be true if a field with the given value is on the page' do\n      expect(@session).to have_select('form_locale', selected: 'English')\n      expect(@session).to have_select('Region', selected: 'Norway')\n      expect(@session).to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n\n    it 'should be false if the given field is not on the page' do\n      expect(@session).not_to have_select('Locale', selected: 'Swedish')\n      expect(@session).not_to have_select('Does not exist', selected: 'John')\n      expect(@session).not_to have_select('City', selected: 'Not there')\n      expect(@session).not_to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns', 'Nonexistent'\n      ])\n      expect(@session).not_to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n      expect(@session).not_to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\"\n      ])\n    end\n\n    it 'should be true after the given value is selected' do\n      @session.select('Swedish', from: 'Locale')\n      expect(@session).to have_select('Locale', selected: 'Swedish')\n    end\n\n    it 'should be false after a different value is selected' do\n      @session.select('Swedish', from: 'Locale')\n      expect(@session).not_to have_select('Locale', selected: 'English')\n    end\n\n    it 'should be true after the given values are selected' do\n      @session.select('Boxers', from: 'Underwear')\n      expect(@session).to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n\n    it 'should be false after one of the values is unselected' do\n      @session.unselect('Briefs', from: 'Underwear')\n      expect(@session).not_to have_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n\n    it \"should be true even when the selected option invisible, regardless of the select's visibility\" do\n      expect(@session).to have_select('Icecream', visible: :hidden, selected: 'Chocolate')\n      expect(@session).to have_select('Sorbet', selected: 'Vanilla')\n    end\n  end\n\n  context 'with partial select' do\n    it 'should be true if a field with the given partial values is on the page' do\n      expect(@session).to have_select('Underwear', with_selected: %w[Boxerbriefs Briefs])\n    end\n\n    it 'should be false if a field with the given partial values is not on the page' do\n      expect(@session).not_to have_select('Underwear', with_selected: %w[Boxerbriefs Boxers])\n    end\n\n    it 'should be true after the given partial value is selected' do\n      @session.select('Boxers', from: 'Underwear')\n      expect(@session).to have_select('Underwear', with_selected: %w[Boxerbriefs Boxers])\n    end\n\n    it 'should be false after one of the given partial values is unselected' do\n      @session.unselect('Briefs', from: 'Underwear')\n      expect(@session).not_to have_select('Underwear', with_selected: %w[Boxerbriefs Briefs])\n    end\n\n    it \"should be true even when the selected values are invisible, regardless of the select's visibility\" do\n      expect(@session).to have_select('Dessert', visible: :hidden, with_options: %w[Pudding Tiramisu])\n      expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])\n    end\n\n    it 'should support non array partial values' do\n      expect(@session).to have_select('Underwear', with_selected: 'Briefs')\n      expect(@session).not_to have_select('Underwear', with_selected: 'Boxers')\n    end\n  end\n\n  context 'with exact options' do\n    it 'should be true if a field with the given options is on the page' do\n      expect(@session).to have_select('Region', options: %w[Norway Sweden Finland])\n      expect(@session).to have_select('Tendency', options: [])\n    end\n\n    it 'should be false if the given field is not on the page' do\n      expect(@session).not_to have_select('Locale', options: ['Swedish'])\n      expect(@session).not_to have_select('Does not exist', options: ['John'])\n      expect(@session).not_to have_select('City', options: ['London', 'Made up city'])\n      expect(@session).not_to have_select('Region', options: %w[Norway Sweden])\n      expect(@session).not_to have_select('Region', options: %w[Norway Norway Norway])\n    end\n\n    it 'should be true even when the options are invisible, if the select itself is invisible' do\n      expect(@session).to have_select('Icecream', visible: :hidden, options: %w[Chocolate Vanilla Strawberry])\n    end\n  end\n\n  context 'with enabled options' do\n    it 'should be true if the listed options exist and are enabled' do\n      expect(@session).to have_select('form_title', enabled_options: %w[Mr Mrs Miss])\n    end\n\n    it 'should be false if the listed options do not exist' do\n      expect(@session).not_to have_select('form_title', enabled_options: ['Not there'])\n    end\n\n    it 'should be false if the listed option exists but is not enabled' do\n      expect(@session).not_to have_select('form_title', enabled_options: %w[Mr Mrs Miss Other])\n    end\n  end\n\n  context 'with disabled options' do\n    it 'should be true if the listed options exist and are disabled' do\n      expect(@session).to have_select('form_title', disabled_options: ['Other'])\n    end\n\n    it 'should be false if the listed options do not exist' do\n      expect(@session).not_to have_select('form_title', disabled_options: ['Not there'])\n    end\n\n    it 'should be false if the listed option exists but is not disabled' do\n      expect(@session).not_to have_select('form_title', disabled_options: %w[Other Mrs])\n    end\n  end\n\n  context 'with partial options' do\n    it 'should be true if a field with the given partial options is on the page' do\n      expect(@session).to have_select('Region', with_options: %w[Norway Sweden])\n      expect(@session).to have_select('City', with_options: ['London'])\n    end\n\n    it 'should be false if a field with the given partial options is not on the page' do\n      expect(@session).not_to have_select('Locale', with_options: ['Uruguayan'])\n      expect(@session).not_to have_select('Does not exist', with_options: ['John'])\n      expect(@session).not_to have_select('Region', with_options: %w[Norway Sweden Finland Latvia])\n    end\n\n    it 'should be true even when the options are invisible, if the select itself is invisible' do\n      expect(@session).to have_select('Icecream', visible: :hidden, with_options: %w[Vanilla Strawberry])\n    end\n  end\n\n  context 'with multiple option' do\n    it 'should find multiple selects if true' do\n      expect(@session).to have_select('form_languages', multiple: true)\n      expect(@session).not_to have_select('form_other_title', multiple: true)\n    end\n\n    it 'should not find multiple selects if false' do\n      expect(@session).not_to have_select('form_languages', multiple: false)\n      expect(@session).to have_select('form_other_title', multiple: false)\n    end\n\n    it 'should find both if not specified' do\n      expect(@session).to have_select('form_languages')\n      expect(@session).to have_select('form_other_title')\n    end\n  end\n\n  it 'should raise an error if an invalid option is passed' do\n    expect do\n      expect(@session).to have_select('form_languages', invalid: true)\n    end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :disabled, :name, :placeholder, :options, :enabled_options, :disabled_options, :selected, :with_selected, :multiple, :with_options')\n  end\n\n  it 'should support locator-less usage' do\n    expect(@session.has_select?(with_options: %w[Norway Sweden])).to be true\n    expect(@session).to have_select(with_options: ['London'])\n    expect(@session.has_select?(with_selected: %w[Commando Boxerbriefs])).to be true\n    expect(@session).to have_select(with_selected: ['Briefs'])\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_select?' do\n  before { @session.visit('/form') }\n\n  it 'should be false if the field is on the page' do\n    expect(@session).not_to have_no_select('Locale')\n    expect(@session).not_to have_no_select('form_region')\n    expect(@session).not_to have_no_select('Languages')\n  end\n\n  it 'should be true if the field is not on the page' do\n    expect(@session).to have_no_select('Monkey')\n  end\n\n  context 'with selected value' do\n    it 'should be false if a field with the given value is on the page' do\n      expect(@session).not_to have_no_select('form_locale', selected: 'English')\n      expect(@session).not_to have_no_select('Region', selected: 'Norway')\n      expect(@session).not_to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n\n    it 'should be true if the given field is not on the page' do\n      expect(@session).to have_no_select('Locale', selected: 'Swedish')\n      expect(@session).to have_no_select('Does not exist', selected: 'John')\n      expect(@session).to have_no_select('City', selected: 'Not there')\n      expect(@session).to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns', 'Nonexistent'\n      ])\n      expect(@session).to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n      expect(@session).to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\"\n      ])\n    end\n\n    it 'should be false after the given value is selected' do\n      @session.select('Swedish', from: 'Locale')\n      expect(@session).not_to have_no_select('Locale', selected: 'Swedish')\n    end\n\n    it 'should be true after a different value is selected' do\n      @session.select('Swedish', from: 'Locale')\n      expect(@session).to have_no_select('Locale', selected: 'English')\n    end\n\n    it 'should be false after the given values are selected' do\n      @session.select('Boxers', from: 'Underwear')\n      expect(@session).not_to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n\n    it 'should be true after one of the values is unselected' do\n      @session.unselect('Briefs', from: 'Underwear')\n      expect(@session).to have_no_select('Underwear', selected: [\n        'Boxerbriefs', 'Briefs', 'Commando', \"Frenchman's Pantalons\", 'Long Johns'\n      ])\n    end\n  end\n\n  context 'with partial select' do\n    it 'should be false if a field with the given partial values is on the page' do\n      expect(@session).not_to have_no_select('Underwear', with_selected: %w[Boxerbriefs Briefs])\n    end\n\n    it 'should be true if a field with the given partial values is not on the page' do\n      expect(@session).to have_no_select('Underwear', with_selected: %w[Boxerbriefs Boxers])\n    end\n\n    it 'should be false after the given partial value is selected' do\n      @session.select('Boxers', from: 'Underwear')\n      expect(@session).not_to have_no_select('Underwear', with_selected: %w[Boxerbriefs Boxers])\n    end\n\n    it 'should be true after one of the given partial values is unselected' do\n      @session.unselect('Briefs', from: 'Underwear')\n      expect(@session).to have_no_select('Underwear', with_selected: %w[Boxerbriefs Briefs])\n    end\n\n    it 'should support non array partial values' do\n      expect(@session).not_to have_no_select('Underwear', with_selected: 'Briefs')\n      expect(@session).to have_no_select('Underwear', with_selected: 'Boxers')\n    end\n  end\n\n  context 'with exact options' do\n    it 'should be false if a field with the given options is on the page' do\n      expect(@session).not_to have_no_select('Region', options: %w[Norway Sweden Finland])\n    end\n\n    it 'should be true if the given field is not on the page' do\n      expect(@session).to have_no_select('Locale', options: ['Swedish'])\n      expect(@session).to have_no_select('Does not exist', options: ['John'])\n      expect(@session).to have_no_select('City', options: ['London', 'Made up city'])\n      expect(@session).to have_no_select('Region', options: %w[Norway Sweden])\n      expect(@session).to have_no_select('Region', options: %w[Norway Norway Norway])\n    end\n  end\n\n  context 'with partial options' do\n    it 'should be false if a field with the given partial options is on the page' do\n      expect(@session).not_to have_no_select('Region', with_options: %w[Norway Sweden])\n      expect(@session).not_to have_no_select('City', with_options: ['London'])\n    end\n\n    it 'should be true if a field with the given partial options is not on the page' do\n      expect(@session).to have_no_select('Locale', with_options: ['Uruguayan'])\n      expect(@session).to have_no_select('Does not exist', with_options: ['John'])\n      expect(@session).to have_no_select('Region', with_options: %w[Norway Sweden Finland Latvia])\n    end\n  end\n\n  it 'should support locator-less usage' do\n    expect(@session.has_no_select?(with_options: %w[Norway Sweden Finland Latvia])).to be true\n    expect(@session).to have_no_select(with_options: ['New London'])\n    expect(@session.has_no_select?(id: 'form_underwear', with_selected: ['Boxers'])).to be true\n    expect(@session).to have_no_select(id: 'form_underwear', with_selected: %w[Commando Boxers])\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_selector_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_selector?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selector is on the page' do\n    expect(@session).to have_selector(:xpath, '//p')\n    expect(@session).to have_selector(:css, 'p a#foo')\n    expect(@session).to have_selector(\"//p[contains(.,'est')]\")\n  end\n\n  it 'should be false if the given selector is not on the page' do\n    expect(@session).not_to have_selector(:xpath, '//abbr')\n    expect(@session).not_to have_selector(:css, 'p a#doesnotexist')\n    expect(@session).not_to have_selector(\"//p[contains(.,'thisstringisnotonpage')]\")\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(@session).not_to have_selector('p a#doesnotexist')\n    expect(@session).to have_selector('p a#foo')\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect(@session).to have_selector(\".//a[@id='foo']\")\n      expect(@session).not_to have_selector(\".//a[@id='red']\")\n    end\n  end\n\n  it 'should accept a filter block' do\n    expect(@session).to have_selector(:css, 'a', count: 1) { |el| el[:id] == 'foo' }\n  end\n\n  context 'with count' do\n    it 'should be true if the content is on the page the given number of times' do\n      expect(@session).to have_selector('//p', count: 3)\n      expect(@session).to have_selector(\"//p//a[@id='foo']\", count: 1)\n      expect(@session).to have_selector(\"//p[contains(.,'est')]\", count: 1)\n    end\n\n    it 'should be false if the content is on the page the given number of times' do\n      expect(@session).not_to have_selector('//p', count: 6)\n      expect(@session).not_to have_selector(\"//p//a[@id='foo']\", count: 2)\n      expect(@session).not_to have_selector(\"//p[contains(.,'est')]\", count: 5)\n    end\n\n    it \"should be false if the content isn't on the page at all\" do\n      expect(@session).not_to have_selector('//abbr', count: 2)\n      expect(@session).not_to have_selector(\"//p//a[@id='doesnotexist']\", count: 1)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      expect(@session).to have_selector('//p//a', text: 'Redirect', count: 1)\n      expect(@session).to have_selector(:css, 'p a', text: 'Redirect', count: 1)\n      expect(@session).not_to have_selector('//p', text: 'Doesnotexist')\n    end\n\n    it 'should respect visibility setting' do\n      expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)\n      expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)\n      Capybara.ignore_hidden_elements = false\n      expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)\n      Capybara.visible_text_only = true\n      expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)\n    end\n\n    it 'should discard all matches where the given regexp is not matched' do\n      expect(@session).to have_selector('//p//a', text: /re[dab]i/i, count: 1)\n      expect(@session).not_to have_selector('//p//a', text: /Red$/)\n    end\n\n    it 'should raise when extra parameters passed' do\n      expect do\n        expect(@session).to have_selector(:css, 'p a#foo', 'extra')\n      end.to raise_error ArgumentError, /extra/\n    end\n\n    context 'with whitespace normalization' do\n      context 'Capybara.default_normalize_ws = false' do\n        it 'should support normalize_ws option' do\n          Capybara.default_normalize_ws = false\n          expect(@session).not_to have_selector(:id, 'second', text: 'text with whitespace')\n          expect(@session).to have_selector(:id, 'second', text: 'text with whitespace', normalize_ws: true)\n        end\n      end\n\n      context 'Capybara.default_normalize_ws = true' do\n        it 'should support normalize_ws option' do\n          Capybara.default_normalize_ws = true\n          expect(@session).to have_selector(:id, 'second', text: 'text with whitespace')\n          expect(@session).not_to have_selector(:id, 'second', text: 'text with whitespace', normalize_ws: false)\n        end\n      end\n    end\n  end\n\n  context 'with exact_text' do\n    context 'string' do\n      it 'should only match elements that match exactly' do\n        expect(@session).to have_selector(:id, 'h2one', exact_text: 'Header Class Test One')\n        expect(@session).to have_no_selector(:id, 'h2one', exact_text: 'Header Class Test')\n      end\n    end\n\n    context 'boolean' do\n      it 'should only match elements that match exactly when true' do\n        expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test One', exact_text: true)\n        expect(@session).to have_no_selector(:id, 'h2one', text: 'Header Class Test', exact_text: true)\n      end\n\n      it 'should match substrings when false' do\n        expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test One', exact_text: false)\n        expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test', exact_text: false)\n      end\n\n      it 'should warn if text option is a regexp that it is ignoring exact_text' do\n        allow(Capybara::Helpers).to receive(:warn)\n        expect(@session).to have_selector(:id, 'h2one', text: /Class Test/, exact_text: true)\n        expect(Capybara::Helpers).to have_received(:warn).with(/'exact_text' option is not supported/)\n      end\n    end\n\n    context 'regexp' do\n      it 'should only match when it fully matches' do\n        expect(@session).to have_selector(:id, 'h2one', exact_text: /Header Class Test One/)\n        expect(@session).to have_no_selector(:id, 'h2one', exact_text: /Header Class Test/)\n        expect(@session).to have_no_selector(:id, 'h2one', exact_text: /Class Test One/)\n        expect(@session).to have_no_selector(:id, 'h2one', exact_text: /Class Test/)\n      end\n    end\n  end\n\n  context 'datalist' do\n    it 'should match options' do\n      @session.visit('/form')\n      expect(@session).to have_selector(:datalist_input, with_options: %w[Jaguar Audi Mercedes])\n      expect(@session).not_to have_selector(:datalist_input, with_options: %w[Ford Chevy])\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_selector?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given selector is on the page' do\n    expect(@session).not_to have_no_selector(:xpath, '//p')\n    expect(@session).not_to have_no_selector(:css, 'p a#foo')\n    expect(@session).not_to have_no_selector(\"//p[contains(.,'est')]\")\n  end\n\n  it 'should be true if the given selector is not on the page' do\n    expect(@session).to have_no_selector(:xpath, '//abbr')\n    expect(@session).to have_no_selector(:css, 'p a#doesnotexist')\n    expect(@session).to have_no_selector(\"//p[contains(.,'thisstringisnotonpage')]\")\n  end\n\n  it 'should use default selector' do\n    Capybara.default_selector = :css\n    expect(@session).to have_no_selector('p a#doesnotexist')\n    expect(@session).not_to have_no_selector('p a#foo')\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect(@session).not_to have_no_selector(\".//a[@id='foo']\")\n      expect(@session).to have_no_selector(\".//a[@id='red']\")\n    end\n  end\n\n  it 'should accept a filter block' do\n    expect(@session).to have_no_selector(:css, 'a#foo') { |el| el[:id] != 'foo' }\n  end\n\n  context 'with count' do\n    it 'should be false if the content is on the page the given number of times' do\n      expect(@session).not_to have_no_selector('//p', count: 3)\n      expect(@session).not_to have_no_selector(\"//p//a[@id='foo']\", count: 1)\n      expect(@session).not_to have_no_selector(\"//p[contains(.,'est')]\", count: 1)\n    end\n\n    it 'should be true if the content is on the page the wrong number of times' do\n      expect(@session).to have_no_selector('//p', count: 6)\n      expect(@session).to have_no_selector(\"//p//a[@id='foo']\", count: 2)\n      expect(@session).to have_no_selector(\"//p[contains(.,'est')]\", count: 5)\n    end\n\n    it \"should be true if the content isn't on the page at all\" do\n      expect(@session).to have_no_selector('//abbr', count: 2)\n      expect(@session).to have_no_selector(\"//p//a[@id='doesnotexist']\", count: 1)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is contained' do\n      expect(@session).not_to have_no_selector('//p//a', text: 'Redirect', count: 1)\n      expect(@session).to have_no_selector('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is matched' do\n      expect(@session).not_to have_no_selector('//p//a', text: /re[dab]i/i, count: 1)\n      expect(@session).to have_no_selector('//p//a', text: /Red$/)\n    end\n\n    it 'should error when matching element exists' do\n      expect do\n        expect(@session).to have_no_selector('//h2', text: 'Header Class Test Five')\n      end.to raise_error RSpec::Expectations::ExpectationNotMetError\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_sibling_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#have_sibling' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should assert a prior sibling element using the given locator' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el).to have_sibling(:css, '#pre_sibling')\n  end\n\n  it 'should assert a following sibling element using the given locator' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el).to have_sibling(:css, '#post_sibling')\n  end\n\n  it 'should not raise an error if there are multiple matches' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el).to have_sibling(:css, 'div')\n  end\n\n  it 'should allow counts to be specified' do\n    el = @session.find(:css, '#mid_sibling')\n\n    expect(el).to have_sibling(:css, 'div').exactly(2).times\n    expect do\n      expect(el).to have_sibling(:css, 'div').once\n    end.to raise_error(RSpec::Expectations::ExpectationNotMetError)\n  end\nend\n\nCapybara::SpecHelper.spec '#have_no_sibling' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should assert no matching sibling' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el).to have_no_sibling(:css, '#not_a_sibling')\n    expect(el).not_to have_sibling(:css, '#not_a_sibling')\n  end\n\n  it 'should raise if there are matching siblings' do\n    el = @session.find(:css, '#mid_sibling')\n    expect do\n      expect(el).to have_no_sibling(:css, '#pre_sibling')\n    end.to raise_error(RSpec::Expectations::ExpectationNotMetError)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_table_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_table?' do\n  before do\n    @session.visit('/tables')\n  end\n\n  it 'should be true if the table is on the page' do\n    expect(@session).to have_table('Villain')\n    expect(@session).to have_table('villain_table')\n    expect(@session).to have_table(:villain_table)\n  end\n\n  it 'should accept rows with column header hashes' do\n    expect(@session).to have_table('Horizontal Headers', with_rows:\n      [\n        { 'First Name' => 'Vern', 'Last Name' => 'Konopelski', 'City' => 'Everette' },\n        { 'First Name' => 'Palmer', 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }\n      ])\n  end\n\n  it 'should accept rows with partial column header hashes' do\n    expect(@session).to have_table('Horizontal Headers', with_rows:\n      [\n        { 'First Name' => 'Thomas' },\n        { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }\n      ])\n\n    expect(@session).not_to have_table('Horizontal Headers', with_rows:\n      [\n        { 'Unmatched Header' => 'Thomas' }\n      ])\n  end\n\n  it 'should accept rows with array of cell values' do\n    expect(@session).to have_table('Horizontal Headers', with_rows:\n      [\n        %w[Thomas Walpole Oceanside],\n        ['Ratke', 'Lawrence', 'East Sorayashire']\n      ])\n  end\n\n  it 'should consider order of cells in each row' do\n    expect(@session).not_to have_table('Horizontal Headers', with_rows:\n      [\n        %w[Thomas Walpole Oceanside],\n        ['Lawrence', 'Ratke', 'East Sorayashire']\n      ])\n  end\n\n  it 'should accept all rows with array of cell values' do\n    expect(@session).to have_table('Horizontal Headers', rows:\n      [\n        %w[Thomas Walpole Oceanside],\n        %w[Danilo Wilkinson Johnsonville],\n        %w[Vern Konopelski Everette],\n        ['Ratke', 'Lawrence', 'East Sorayashire'],\n        ['Palmer', 'Sawayn', 'West Trinidad']\n      ])\n  end\n\n  it 'should match with vertical headers' do\n    expect(@session).to have_table('Vertical Headers', with_cols:\n      [\n        { 'First Name' => 'Thomas' },\n        { 'First Name' => 'Danilo', 'Last Name' => 'Wilkinson', 'City' => 'Johnsonville' },\n        { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }\n      ])\n  end\n\n  it 'should match col with array of cell values' do\n    expect(@session).to have_table('Vertical Headers', with_cols:\n      [\n        %w[Vern Konopelski Everette]\n      ])\n  end\n\n  it 'should match cols with array of cell values' do\n    expect(@session).to have_table('Vertical Headers', with_cols:\n      [\n        %w[Danilo Wilkinson Johnsonville],\n        %w[Vern Konopelski Everette]\n      ])\n  end\n\n  it 'should match all cols with array of cell values' do\n    expect(@session).to have_table('Vertical Headers', cols:\n      [\n        %w[Thomas Walpole Oceanside],\n        %w[Danilo Wilkinson Johnsonville],\n        %w[Vern Konopelski Everette],\n        ['Ratke', 'Lawrence', 'East Sorayashire'],\n        ['Palmer', 'Sawayn', 'West Trinidad']\n      ])\n  end\n\n  it \"should not match if the order of cell values doesn't match\" do\n    expect(@session).not_to have_table('Vertical Headers', with_cols:\n      [\n        %w[Vern Everette Konopelski]\n      ])\n  end\n\n  it \"should not match with vertical headers if the columns don't match\" do\n    expect(@session).not_to have_table('Vertical Headers', with_cols:\n      [\n        { 'First Name' => 'Thomas' },\n        { 'First Name' => 'Danilo', 'Last Name' => 'Walpole', 'City' => 'Johnsonville' },\n        { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }\n      ])\n\n    expect(@session).not_to have_table('Vertical Headers', with_cols:\n      [\n        { 'Unmatched Header' => 'Thomas' }\n      ])\n  end\n\n  it 'should be false if the table is not on the page' do\n    expect(@session).not_to have_table('Monkey')\n  end\n\n  it 'should find row by header and cell values' do\n    expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'First Name' => 'Thomas', 'Last Name' => 'Walpole')\n    expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'Last Name' => 'Walpole')\n    expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, 'First Name' => 'Walpole')\n    expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, 'Unmatched Header' => 'Thomas')\n  end\n\n  it 'should find row by cell values' do\n    expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, %w[Thomas Walpole Oceanside])\n    expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Walpole Thomas])\n    expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Other])\n  end\n\n  it 'should find row by all rows without locator values' do\n    table = @session.find(:table, 'Horizontal Headers')\n\n    expect(table).to have_selector(:table_row)\n    expect(table).to have_selector(:table_row, count: 6)\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_table?' do\n  before do\n    @session.visit('/tables')\n  end\n\n  it 'should be false if the table is on the page' do\n    expect(@session).not_to have_no_table('Villain')\n    expect(@session).not_to have_no_table('villain_table')\n  end\n\n  it 'should be true if the table is not on the page' do\n    expect(@session).to have_no_table('Monkey')\n  end\n\n  it 'should consider rows' do\n    expect(@session).to have_no_table('Horizontal Headers', with_rows:\n     [\n       { 'First Name' => 'Thomas', 'City' => 'Los Angeles' }\n     ])\n  end\n\n  context 'using :with_cols' do\n    it 'should consider a single column' do\n      expect(@session).to have_no_table('Vertical Headers', with_cols:\n        [\n          { 'First Name' => 'Joe' }\n        ])\n    end\n\n    it 'should be true even if the last column does exist' do\n      expect(@session).to have_no_table('Vertical Headers', with_cols:\n        [\n          {\n            'First Name' => 'What?',\n            'What?' => 'Walpole',\n            'City' => 'Oceanside' # This line makes the example fail\n          }\n        ])\n    end\n\n    it 'should be true if none of the columns exist' do\n      expect(@session).to have_no_table('Vertical Headers', with_cols:\n        [\n          {\n            'First Name' => 'What?',\n            'What?' => 'Walpole',\n            'City' => 'What?'\n          }\n        ])\n    end\n\n    it 'should be true if the first column does match' do\n      expect(@session).to have_no_table('Vertical Headers', with_cols:\n        [\n          {\n            'First Name' => 'Thomas',\n            'Last Name' => 'What',\n            'City' => 'What'\n          }\n        ])\n    end\n\n    it 'should be true if none of the columns match' do\n      expect(@session).to have_no_table('Vertical Headers', with_cols:\n        [\n          {\n            'First Name' => 'What',\n            'Last Name' => 'What',\n            'City' => 'What'\n          }\n        ])\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_text_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_text?' do\n  it 'should be true if the given text is on the page at least once' do\n    @session.visit('/with_html')\n    expect(@session).to have_text('est')\n    expect(@session).to have_text('Lorem')\n    expect(@session).to have_text('Redirect')\n    expect(@session).to have_text(:Redirect)\n  end\n\n  it 'should be true if scoped to an element which has the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session).to have_text('labore')\n    end\n  end\n\n  it 'should be false if scoped to an element which does not have the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session).not_to have_text('monkey')\n    end\n  end\n\n  it 'should ignore tags' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_text('exercitation <a href=\"/foo\" id=\"foo\">ullamco</a> laboris')\n    expect(@session).to have_text('exercitation ullamco laboris')\n  end\n\n  it 'should search correctly normalized text' do\n    @session.visit('/with_html')\n    expect(@session).to have_text('text with   whitespace')\n  end\n\n  it 'should search whitespace collapsed text' do\n    @session.visit('/with_html')\n    expect(@session).to have_text('text with whitespace', normalize_ws: true)\n  end\n\n  context 'with enabled default collapsing whitespace' do\n    before { Capybara.default_normalize_ws = true }\n\n    it 'should search unnormalized text' do\n      @session.visit('/with_html')\n      expect(@session).to have_text('text with   whitespace', normalize_ws: false)\n    end\n\n    it 'should search whitespace collapsed text' do\n      @session.visit('/with_html')\n      expect(@session).to have_text('text with whitespace')\n    end\n  end\n\n  it 'should be false if the given text is not on the page' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_text('xxxxyzzz')\n    expect(@session).not_to have_text('monkey')\n  end\n\n  it 'should handle single quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).to have_text(\"can't\")\n  end\n\n  it 'should handle double quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).to have_text('\"No,\" he said')\n  end\n\n  it 'should handle mixed single and double quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).to have_text(%q(\"you can't do that.\"))\n  end\n\n  it 'should be false if text is in the title tag in the head' do\n    @session.visit('/with_js')\n    expect(@session).not_to have_text('with_js')\n  end\n\n  it 'should be false if text is inside a script tag in the body' do\n    @session.visit('/with_js')\n    expect(@session).not_to have_text('a javascript comment')\n    expect(@session).not_to have_text('aVar')\n  end\n\n  it 'should be false if the given text is on the page but not visible' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_text('Inside element with hidden ancestor')\n  end\n\n  it 'should be true if :all given and text is invisible.' do\n    @session.visit('/with_html')\n    expect(@session).to have_text(:all, 'Some of this text is hidden!')\n  end\n\n  it 'should be true if `Capybara.ignore_hidden_elements = false` and text is invisible.' do\n    Capybara.ignore_hidden_elements = false\n    @session.visit('/with_html')\n    expect(@session).to have_text('Some of this text is hidden!')\n  end\n\n  it 'should be true if the text in the page matches given regexp' do\n    @session.visit('/with_html')\n    expect(@session).to have_text(/Lorem/)\n  end\n\n  it \"should be false if the text in the page doesn't match given regexp\" do\n    @session.visit('/with_html')\n    expect(@session).not_to have_text(/xxxxyzzz/)\n  end\n\n  context 'with object implementing to_s and to_hash' do\n    it 'should work if the object is passed alone' do\n      with_to_hash = Class.new do\n        def to_s; '42' end\n        def to_hash; { value: 'Other hash' } end\n      end.new\n      @session.visit('/with_html')\n      expect(@session).to have_text(with_to_hash)\n    end\n\n    it 'should work if passed with empty options' do\n      with_to_hash = Class.new do\n        def to_s; '42' end\n        def to_hash; { value: 'Other hash' } end\n      end.new\n      @session.visit('/with_html')\n      expect(@session).to have_text(:visible, with_to_hash, **{})\n    end\n  end\n\n  context 'with exact: true option' do\n    it 'should be true if text matches exactly' do\n      @session.visit('/with_html')\n      expect(@session.find(:id, 'h2one')).to have_text('Header Class Test One', exact: true)\n    end\n\n    it \"should be false if text doesn't match exactly\" do\n      @session.visit('/with_html')\n      expect(@session.find(:id, 'h2one')).not_to have_text('Header Class Test On', exact: true)\n    end\n  end\n\n  it 'should escape any characters that would have special meaning in a regexp' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_text('.orem')\n  end\n\n  it 'should accept non-string parameters' do\n    @session.visit('/with_html')\n    expect(@session).to have_text(42)\n  end\n\n  it 'should be true when passed nil, and warn about it' do\n    # nil is converted to '' when to_s is invoked\n    @session.visit('/with_html')\n    expect do\n      expect(@session).to have_text(nil)\n    end.to output(/Checking for expected text of nil is confusing/).to_stderr\n  end\n\n  it 'should wait for text to appear', requires: [:js] do\n    Capybara.using_wait_time(3) do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect(@session).to have_text('Has been clicked')\n    end\n  end\n\n  context 'with between' do\n    it 'should be true if the text occurs within the range given' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', between: 1..3)\n      expect(@session).to have_text(/count/, between: 2..2)\n    end\n\n    it 'should be false if the text occurs more or fewer times than range' do\n      @session.visit('/with_count')\n      expect(@session).not_to have_text('count', between: 0..1)\n      expect(@session).not_to have_text('count', between: 3..10)\n      expect(@session).not_to have_text(/count/, between: 2...2)\n    end\n  end\n\n  context 'with count' do\n    it 'should be true if the text occurs the given number of times' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', count: 2)\n      expect(@session).to have_text('count').exactly(2).times\n    end\n\n    it 'should be false if the text occurs a different number of times than the given' do\n      @session.visit('/with_count')\n      expect(@session).not_to have_text('count', count: 0)\n      expect(@session).not_to have_text('count', count: 1)\n      expect(@session).not_to have_text('count').once\n      expect(@session).not_to have_text(/count/, count: 3)\n    end\n\n    it 'should coerce count to an integer' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', count: '2')\n      expect(@session).not_to have_text('count', count: '3')\n    end\n  end\n\n  context 'with maximum' do\n    it 'should be true when text occurs same or fewer times than given' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', maximum: 2)\n      expect(@session).to have_text('count').at_most(2).times\n      expect(@session).to have_text(/count/, maximum: 3)\n    end\n\n    it 'should be false when text occurs more times than given' do\n      @session.visit('/with_count')\n      expect(@session).not_to have_text('count', maximum: 1)\n      expect(@session).not_to have_text('count').at_most(1).times\n      expect(@session).not_to have_text('count', maximum: 0)\n    end\n\n    it 'should coerce maximum to an integer' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', maximum: '2')\n      expect(@session).not_to have_text('count', maximum: '1')\n    end\n  end\n\n  context 'with minimum' do\n    it 'should be true when text occurs same or more times than given' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', minimum: 2)\n      expect(@session).to have_text('count').at_least(2).times\n      expect(@session).to have_text(/count/, minimum: 0)\n    end\n\n    it 'should be false when text occurs fewer times than given' do\n      @session.visit('/with_count')\n      expect(@session).not_to have_text('count', minimum: 3)\n      expect(@session).not_to have_text('count').at_least(3).times\n    end\n\n    it 'should coerce minimum to an integer' do\n      @session.visit('/with_count')\n      expect(@session).to have_text('count', minimum: '2')\n      expect(@session).not_to have_text('count', minimum: '3')\n    end\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should find element if it appears before given wait duration' do\n      Capybara.using_wait_time(0.1) do\n        @session.visit('/with_js')\n        @session.click_link('Click me')\n        expect(@session).to have_text('Has been clicked', wait: 3)\n      end\n    end\n  end\n\n  it 'should raise an error if an invalid option is passed' do\n    @session.visit('/with_html')\n    expect do\n      expect(@session).to have_text('Lorem', invalid: true)\n    end.to raise_error(ArgumentError)\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_text?' do\n  it 'should be false if the given text is on the page at least once' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_no_text('est')\n    expect(@session).not_to have_no_text('Lorem')\n    expect(@session).not_to have_no_text('Redirect')\n  end\n\n  it 'should be false if scoped to an element which has the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session).not_to have_no_text('labore')\n    end\n  end\n\n  it 'should be true if scoped to an element which does not have the text' do\n    @session.visit('/with_html')\n    @session.within(\"//a[@title='awesome title']\") do\n      expect(@session).to have_no_text('monkey')\n    end\n  end\n\n  it 'should ignore tags' do\n    @session.visit('/with_html')\n    expect(@session).to have_no_text('exercitation <a href=\"/foo\" id=\"foo\">ullamco</a> laboris')\n    expect(@session).not_to have_no_text('exercitation ullamco laboris')\n  end\n\n  it 'should be true if the given text is not on the page' do\n    @session.visit('/with_html')\n    expect(@session).to have_no_text('xxxxyzzz')\n    expect(@session).to have_no_text('monkey')\n  end\n\n  it 'should handle single quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).not_to have_no_text(\"can't\")\n  end\n\n  it 'should handle double quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).not_to have_no_text('\"No,\" he said')\n  end\n\n  it 'should handle mixed single and double quotes in the text' do\n    @session.visit('/with-quotes')\n    expect(@session).not_to have_no_text(%q(\"you can't do that.\"))\n  end\n\n  it 'should be true if text is in the title tag in the head' do\n    @session.visit('/with_js')\n    expect(@session).to have_no_text('with_js')\n  end\n\n  it 'should be true if text is inside a script tag in the body' do\n    @session.visit('/with_js')\n    expect(@session).to have_no_text('a javascript comment')\n    expect(@session).to have_no_text('aVar')\n  end\n\n  it 'should be true if the given text is on the page but not visible' do\n    @session.visit('/with_html')\n    expect(@session).to have_no_text('Inside element with hidden ancestor')\n  end\n\n  it 'should be false if :all given and text is invisible.' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_no_text(:all, 'Some of this text is hidden!')\n  end\n\n  it 'should be false if `Capybara.ignore_hidden_elements = false` and text is invisible.' do\n    Capybara.ignore_hidden_elements = false\n    @session.visit('/with_html')\n    expect(@session).not_to have_no_text('Some of this text is hidden!')\n  end\n\n  it \"should be true if the text in the page doesn't match given regexp\" do\n    @session.visit('/with_html')\n    expect(@session).to have_no_text(/xxxxyzzz/)\n  end\n\n  it 'should be false if the text in the page matches given regexp' do\n    @session.visit('/with_html')\n    expect(@session).not_to have_no_text(/Lorem/)\n  end\n\n  it 'should escape any characters that would have special meaning in a regexp' do\n    @session.visit('/with_html')\n    expect(@session).to have_no_text('.orem')\n  end\n\n  it 'should wait for text to disappear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session).to have_no_text('I changed it')\n  end\n\n  context 'with wait', requires: [:js] do\n    it 'should not find element if it appears after given wait duration' do\n      @session.visit('/with_js')\n      @session.click_link('Click me')\n      expect(@session).to have_no_text('Has been clicked', wait: 0.05)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_title_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_title?' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should be true if the page has the given title' do\n    expect(@session).to have_title('with_js')\n    expect(@session.has_title?('with_js')).to be true\n  end\n\n  it 'should allow regexp matches' do\n    expect(@session).to have_title(/w[a-z]{3}_js/)\n    expect(@session).not_to have_title(/monkey/)\n  end\n\n  it 'should wait for title', requires: [:js] do\n    @session.click_link('Change title')\n    expect(@session).to have_title('changed title')\n  end\n\n  it 'should be false if the page has not the given title' do\n    expect(@session).not_to have_title('monkey')\n    expect(@session.has_title?('monkey')).to be false\n  end\n\n  it 'should default to exact: false matching' do\n    expect(@session).to have_title('with_js', exact: false)\n    expect(@session).to have_title('with_', exact: false)\n  end\n\n  it 'should match exactly if exact: true option passed' do\n    expect(@session).to have_title('with_js', exact: true)\n    expect(@session).not_to have_title('with_', exact: true)\n    expect(@session.has_title?('with_js', exact: true)).to be true\n    expect(@session.has_title?('with_', exact: true)).to be false\n  end\n\n  it 'should match partial if exact: false option passed' do\n    expect(@session).to have_title('with_js', exact: false)\n    expect(@session).to have_title('with_', exact: false)\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_title?' do\n  before do\n    @session.visit('/with_js')\n  end\n\n  it 'should be false if the page has the given title' do\n    expect(@session).not_to have_no_title('with_js')\n  end\n\n  it 'should allow regexp matches' do\n    expect(@session).not_to have_no_title(/w[a-z]{3}_js/)\n    expect(@session).to have_no_title(/monkey/)\n  end\n\n  it 'should wait for title to disappear', requires: [:js] do\n    Capybara.using_wait_time(5) do\n      @session.click_link('Change title') # triggers title change after 400ms\n      expect(@session).to have_no_title('with_js')\n    end\n  end\n\n  it 'should be true if the page has not the given title' do\n    expect(@session).to have_no_title('monkey')\n    expect(@session.has_no_title?('monkey')).to be true\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/has_xpath_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#has_xpath?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the given selector is on the page' do\n    expect(@session).to have_xpath('//p')\n    expect(@session).to have_xpath(\"//p//a[@id='foo']\")\n    expect(@session).to have_xpath(\"//p[contains(.,'est')]\")\n  end\n\n  it 'should support :id option' do\n    expect(@session).to have_xpath('//h2', id: 'h2one')\n    expect(@session).to have_xpath('//h2')\n    expect(@session).to have_xpath('//h2', id: /h2o/)\n  end\n\n  it 'should support :class option' do\n    expect(@session).to have_xpath('//li', class: 'guitarist')\n    expect(@session).to have_xpath('//li', class: /guitar/)\n    expect(@session).to have_xpath('//li', class: /guitar|drummer/)\n    expect(@session).to have_xpath('//li', class: %w[beatle guitarist])\n    expect(@session).to have_xpath('//li', class: /.*/)\n  end\n\n  it 'should be false if the given selector is not on the page' do\n    expect(@session).not_to have_xpath('//abbr')\n    expect(@session).not_to have_xpath(\"//p//a[@id='doesnotexist']\")\n    expect(@session).not_to have_xpath(\"//p[contains(.,'thisstringisnotonpage')]\")\n  end\n\n  it 'should use xpath even if default selector is CSS' do\n    Capybara.default_selector = :css\n    expect(@session).not_to have_xpath(\"//p//a[@id='doesnotexist']\")\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect(@session).to have_xpath(\".//a[@id='foo']\")\n      expect(@session).not_to have_xpath(\".//a[@id='red']\")\n    end\n  end\n\n  it 'should wait for content to appear', requires: [:js] do\n    Capybara.using_wait_time(3) do\n      @session.visit('/with_js')\n      @session.click_link('Click me') # updates page after 500ms\n      expect(@session).to have_xpath(\"//input[@type='submit' and @value='New Here']\")\n    end\n  end\n\n  context 'with count' do\n    it 'should be true if the content occurs the given number of times' do\n      expect(@session).to have_xpath('//p', count: 3)\n      expect(@session).to have_xpath(\"//p//a[@id='foo']\", count: 1)\n      expect(@session).to have_xpath(\"//p[contains(.,'est')]\", count: 1)\n      expect(@session).to have_xpath(\"//p//a[@id='doesnotexist']\", count: 0)\n      expect(@session).to have_xpath('//li', class: /guitar|drummer/, count: 4)\n      expect(@session).to have_xpath('//li', id: /john|paul/, class: /guitar|drummer/, count: 2)\n      expect(@session).to have_xpath('//li', class: %w[beatle guitarist], count: 2)\n    end\n\n    it 'should be false if the content occurs a different number of times than the given' do\n      expect(@session).not_to have_xpath('//p', count: 6)\n      expect(@session).not_to have_xpath(\"//p//a[@id='foo']\", count: 2)\n      expect(@session).not_to have_xpath(\"//p[contains(.,'est')]\", count: 5)\n      expect(@session).not_to have_xpath(\"//p//a[@id='doesnotexist']\", count: 1)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is not contained' do\n      expect(@session).to have_xpath('//p//a', text: 'Redirect', count: 1)\n      expect(@session).not_to have_xpath('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is not matched' do\n      expect(@session).to have_xpath('//p//a', text: /re[dab]i/i, count: 1)\n      expect(@session).not_to have_xpath('//p//a', text: /Red$/)\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#has_no_xpath?' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be false if the given selector is on the page' do\n    expect(@session).not_to have_no_xpath('//p')\n    expect(@session).not_to have_no_xpath(\"//p//a[@id='foo']\")\n    expect(@session).not_to have_no_xpath(\"//p[contains(.,'est')]\")\n  end\n\n  it 'should be true if the given selector is not on the page' do\n    expect(@session).to have_no_xpath('//abbr')\n    expect(@session).to have_no_xpath(\"//p//a[@id='doesnotexist']\")\n    expect(@session).to have_no_xpath(\"//p[contains(.,'thisstringisnotonpage')]\")\n  end\n\n  it 'should use xpath even if default selector is CSS' do\n    Capybara.default_selector = :css\n    expect(@session).to have_no_xpath(\"//p//a[@id='doesnotexist']\")\n  end\n\n  it 'should respect scopes' do\n    @session.within \"//p[@id='first']\" do\n      expect(@session).not_to have_no_xpath(\".//a[@id='foo']\")\n      expect(@session).to have_no_xpath(\".//a[@id='red']\")\n    end\n  end\n\n  it 'should wait for content to disappear', requires: [:js] do\n    Capybara.default_max_wait_time = 2\n    @session.visit('/with_js')\n    @session.click_link('Click me')\n    expect(@session).to have_no_xpath(\"//p[@id='change']\")\n  end\n\n  context 'with count' do\n    it 'should be false if the content occurs the given number of times' do\n      expect(@session).not_to have_no_xpath('//p', count: 3)\n      expect(@session).not_to have_no_xpath(\"//p//a[@id='foo']\", count: 1)\n      expect(@session).not_to have_no_xpath(\"//p[contains(.,'est')]\", count: 1)\n      expect(@session).not_to have_no_xpath(\"//p//a[@id='doesnotexist']\", count: 0)\n    end\n\n    it 'should be true if the content occurs a different number of times than the given' do\n      expect(@session).to have_no_xpath('//p', count: 6)\n      expect(@session).to have_no_xpath(\"//p//a[@id='foo']\", count: 2)\n      expect(@session).to have_no_xpath(\"//p[contains(.,'est')]\", count: 5)\n      expect(@session).to have_no_xpath(\"//p//a[@id='doesnotexist']\", count: 1)\n    end\n  end\n\n  context 'with text' do\n    it 'should discard all matches where the given string is contained' do\n      expect(@session).not_to have_no_xpath('//p//a', text: 'Redirect', count: 1)\n      expect(@session).to have_no_xpath('//p', text: 'Doesnotexist')\n    end\n\n    it 'should discard all matches where the given regexp is matched' do\n      expect(@session).not_to have_no_xpath('//p//a', text: /re[dab]i/i, count: 1)\n      expect(@session).to have_no_xpath('//p//a', text: /Red$/)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/headers_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#response_headers' do\n  it 'should return response headers', requires: [:response_headers] do\n    @session.visit('/with_simple_html')\n    expect(@session.response_headers['Content-Type']).to match %r{text/html}\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/html_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec '#html' do\n  it 'should return the unmodified page body' do\n    @session.visit('/')\n    expect(@session.html).to include('Hello world!')\n  end\n\n  it 'should return the current state of the page', requires: [:js] do\n    @session.visit('/with_js')\n    sleep 1\n    expect(@session.html).to include('I changed it')\n    expect(@session.html).not_to include('This is text')\n  end\nend\n\nCapybara::SpecHelper.spec '#source' do\n  it 'should return the unmodified page source' do\n    @session.visit('/')\n    expect(@session.source).to include('Hello world!')\n  end\n\n  it 'should return the current state of the page', requires: [:js] do\n    @session.visit('/with_js')\n    sleep 1\n    expect(@session.source).to include('I changed it')\n    expect(@session.source).not_to include('This is text')\n  end\nend\n\nCapybara::SpecHelper.spec '#body' do\n  it 'should return the unmodified page source' do\n    @session.visit('/')\n    expect(@session.body).to include('Hello world!')\n  end\n\n  it 'should return the current state of the page', requires: [:js] do\n    @session.visit('/with_js')\n    sleep 1\n    expect(@session.body).to include('I changed it')\n    expect(@session.body).not_to include('This is text')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/matches_style_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#matches_style?', requires: [:css] do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should be true if the element has the given style' do\n    expect(@session.find(:css, '#first')).to match_style(display: 'block')\n    expect(@session.find(:css, '#first').matches_style?(display: 'block')).to be true\n    expect(@session.find(:css, '#second')).to match_style('display' => 'inline')\n    expect(@session.find(:css, '#second').matches_style?('display' => 'inline')).to be true\n  end\n\n  it 'should be false if the element does not have the given style' do\n    expect(@session.find(:css, '#first').matches_style?('display' => 'inline')).to be false\n    expect(@session.find(:css, '#second').matches_style?(display: 'block')).to be false\n  end\n\n  it 'allows Regexp for value matching' do\n    expect(@session.find(:css, '#first')).to match_style(display: /^bl/)\n    expect(@session.find(:css, '#first').matches_style?('display' => /^bl/)).to be true\n    expect(@session.find(:css, '#first').matches_style?(display: /^in/)).to be false\n  end\n\n  # rubocop:disable Capybara/MatchStyle\n  it 'deprecated has_style?' do\n    expect { have_style(display: /^bl/) }.to \\\n      output(/have_style is deprecated/).to_stderr\n\n    el = @session.find(:css, '#first')\n    allow(Capybara::Helpers).to receive(:warn).and_return(nil)\n    el.has_style?('display' => /^bl/)\n    expect(Capybara::Helpers).to have_received(:warn)\n  end\n  # rubocop:enable Capybara/MatchStyle\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/node_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec 'node' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should act like a session object' do\n    @session.visit('/form')\n    @form = @session.find(:css, '#get-form')\n    expect(@form).to have_field('Middle Name')\n    expect(@form).to have_no_field('Languages')\n    @form.fill_in('Middle Name', with: 'Monkey')\n    @form.click_button('med')\n    expect(extract_results(@session)['middle_name']).to eq('Monkey')\n  end\n\n  it 'should scope CSS selectors' do\n    expect(@session.find(:css, '#second')).to have_no_css('h1')\n  end\n\n  describe '#query_scope' do\n    it 'should have a reference to the element the query was evaluated on if there is one' do\n      node = @session.find(:css, '#first')\n      expect(node.query_scope).to eq(node.session.document)\n      expect(node.find(:css, '#foo').query_scope).to eq(node)\n    end\n  end\n\n  describe '#text' do\n    it 'should extract node texts' do\n      expect(@session.all('//a')[0].text).to eq('labore')\n      expect(@session.all('//a')[1].text).to eq('ullamco')\n    end\n\n    it 'should return document text on /html selector' do\n      @session.visit('/with_simple_html')\n      expect(@session.all('/html')[0].text).to eq('Bar')\n    end\n  end\n\n  describe '#[]' do\n    it 'should extract node attributes' do\n      expect(@session.all('//a')[0][:class]).to eq('simple')\n      expect(@session.all('//a')[1][:id]).to eq('foo')\n      expect(@session.all('//input')[0][:type]).to eq('text')\n    end\n\n    it 'should extract boolean node attributes' do\n      expect(@session.find('//input[@id=\"checked_field\"]')[:checked]).to be_truthy\n    end\n  end\n\n  describe '#style', requires: [:css] do\n    it 'should return the computed style value' do\n      expect(@session.find(:css, '#first').style('display')).to eq('display' => 'block')\n      expect(@session.find(:css, '#second').style(:display)).to eq('display' => 'inline')\n    end\n\n    it 'should return multiple style values' do\n      expect(@session.find(:css, '#first').style('display', :'line-height')).to eq('display' => 'block', 'line-height' => '25px')\n    end\n  end\n\n  describe '#value' do\n    it 'should allow retrieval of the value' do\n      expect(@session.find('//textarea[@id=\"normal\"]').value).to eq('banana')\n    end\n\n    it 'should not swallow extra newlines in textarea' do\n      expect(@session.find('//textarea[@id=\"additional_newline\"]').value).to eq(\"\\nbanana\")\n    end\n\n    it 'should not swallow leading newlines for set content in textarea' do\n      @session.find('//textarea[@id=\"normal\"]').set(\"\\nbanana\")\n      expect(@session.find('//textarea[@id=\"normal\"]').value).to eq(\"\\nbanana\")\n    end\n\n    it 'return any HTML content in textarea' do\n      @session.find('//textarea[1]').set('some <em>html</em> here')\n      expect(@session.find('//textarea[1]').value).to eq('some <em>html</em> here')\n    end\n\n    it \"defaults to 'on' for checkbox\" do\n      @session.visit('/form')\n      expect(@session.find('//input[@id=\"valueless_checkbox\"]').value).to eq('on')\n    end\n\n    it \"defaults to 'on' for radio buttons\" do\n      @session.visit('/form')\n      expect(@session.find('//input[@id=\"valueless_radio\"]').value).to eq('on')\n    end\n  end\n\n  describe '#set' do\n    it 'should allow assignment of field value' do\n      expect(@session.first('//input').value).to eq('monkey')\n      @session.first('//input').set('gorilla')\n      expect(@session.first('//input').value).to eq('gorilla')\n    end\n\n    it 'should fill the field even if the caret was not at the end', requires: [:js] do\n      @session.execute_script(\"var el = document.getElementById('test_field'); el.focus(); el.setSelectionRange(0, 0);\")\n      @session.first('//input').set('')\n      expect(@session.first('//input').value).to eq('')\n    end\n\n    if ENV['CAPYBARA_THOROUGH']\n      it 'should raise if the text field is readonly' do\n        expect { @session.first('//input[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)\n      end\n\n      it 'should raise if the textarea is readonly' do\n        expect { @session.first('//textarea[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)\n      end\n    else\n      it 'should not change if the text field is readonly' do\n        @session.first('//input[@readonly]').set('changed')\n        expect(@session.first('//input[@readonly]').value).to eq 'should not change'\n      end\n\n      it 'should not change if the textarea is readonly' do\n        @session.first('//textarea[@readonly]').set('changed')\n        expect(@session.first('//textarea[@readonly]').value).to eq 'textarea should not change'\n      end\n    end\n\n    it 'should use global default options' do\n      Capybara.default_set_options = { clear: :backspace }\n      element = @session.first(:fillable_field, type: 'text')\n      allow(element.base).to receive(:set)\n      element.set('gorilla')\n      expect(element.base).to have_received(:set).with('gorilla', clear: :backspace)\n    end\n\n    context 'with a contenteditable element', requires: [:js] do\n      it 'should allow me to change the contents' do\n        @session.visit('/with_js')\n        @session.find(:css, '#existing_content_editable').set('WYSIWYG')\n        expect(@session.find(:css, '#existing_content_editable').text).to eq('WYSIWYG')\n      end\n\n      it 'should allow me to set the contents' do\n        @session.visit('/with_js')\n        @session.find(:css, '#blank_content_editable').set('WYSIWYG')\n        expect(@session.find(:css, '#blank_content_editable').text).to eq('WYSIWYG')\n      end\n\n      it 'should allow me to change the contents of a child element' do\n        @session.visit('/with_js')\n        @session.find(:css, '#existing_content_editable_child').set('WYSIWYG')\n        expect(@session.find(:css, '#existing_content_editable_child').text).to eq('WYSIWYG')\n        expect(@session.find(:css, '#existing_content_editable_child_parent').text).to eq(\"Some content\\nWYSIWYG\")\n      end\n    end\n\n    it 'should submit single text input forms if ended with \\n' do\n      @session.visit('/form')\n      @session.find(:css, '#single_input').set(\"my entry\\n\")\n      expect(extract_results(@session)['single_input']).to eq('my entry')\n    end\n\n    it 'should not submit single text input forms if ended with \\n and has multiple values' do\n      @session.visit('/form')\n      @session.find(:css, '#two_input_1').set(\"my entry\\n\")\n      expect(@session.find(:css, '#two_input_1').value).to eq(\"my entry\\n\").or(eq 'my entry')\n    end\n  end\n\n  describe '#tag_name' do\n    it 'should extract node tag name' do\n      expect(@session.all('//a')[0].tag_name).to eq('a')\n      expect(@session.all('//a')[1].tag_name).to eq('a')\n      expect(@session.all('//p')[1].tag_name).to eq('p')\n    end\n  end\n\n  describe '#disabled?' do\n    it 'should extract disabled node' do\n      @session.visit('/form')\n      expect(@session.find('//input[@id=\"customer_name\"]')).to be_disabled\n      expect(@session.find('//input[@id=\"customer_email\"]')).not_to be_disabled\n    end\n\n    it 'should see disabled options as disabled' do\n      @session.visit('/form')\n      expect(@session.find('//select[@id=\"form_title\"]/option[1]')).not_to be_disabled\n      expect(@session.find('//select[@id=\"form_title\"]/option[@disabled]')).to be_disabled\n    end\n\n    it 'should see enabled options in disabled select as disabled' do\n      @session.visit('/form')\n      expect(@session.find('//select[@id=\"form_disabled_select\"]/option')).to be_disabled\n      expect(@session.find('//select[@id=\"form_disabled_select\"]/optgroup/option')).to be_disabled\n      expect(@session.find('//select[@id=\"form_title\"]/option[1]')).not_to be_disabled\n    end\n\n    it 'should see enabled options in disabled optgroup as disabled' do\n      @session.visit('/form')\n      expect(@session.find('//option', text: 'A.B.1')).to be_disabled\n      expect(@session.find('//option', text: 'A.2')).not_to be_disabled\n    end\n\n    it 'should see a disabled fieldset as disabled' do\n      @session.visit('/form')\n      expect(@session.find(:xpath, './/fieldset[@id=\"form_disabled_fieldset\"]')).to be_disabled\n    end\n\n    context 'in a disabled fieldset' do\n      # https://html.spec.whatwg.org/#the-fieldset-element\n      it 'should see elements not in first legend as disabled' do\n        @session.visit('/form')\n        expect(@session.find('//input[@id=\"form_disabled_fieldset_child\"]')).to be_disabled\n        expect(@session.find('//input[@id=\"form_disabled_fieldset_second_legend_child\"]')).to be_disabled\n        expect(@session.find('//input[@id=\"form_enabled_fieldset_child\"]')).not_to be_disabled\n      end\n\n      it 'should see elements in first legend as enabled' do\n        @session.visit('/form')\n        expect(@session.find('//input[@id=\"form_disabled_fieldset_legend_child\"]')).not_to be_disabled\n      end\n\n      it 'should sees options not in first legend as disabled' do\n        @session.visit('/form')\n        expect(@session.find('//option', text: 'Disabled Child Option')).to be_disabled\n      end\n    end\n\n    it 'should be boolean' do\n      @session.visit('/form')\n      expect(@session.find('//select[@id=\"form_disabled_select\"]/option').disabled?).to be true\n      expect(@session.find('//select[@id=\"form_disabled_select2\"]/option').disabled?).to be true\n      expect(@session.find('//select[@id=\"form_title\"]/option[1]').disabled?).to be false\n    end\n\n    it 'should be disabled for all elements that are CSS :disabled' do\n      @session.visit('/form')\n      # sanity check\n      expect(@session.all(:css, ':disabled')).to all(be_disabled)\n    end\n  end\n\n  describe '#visible?' do\n    before { Capybara.ignore_hidden_elements = false }\n\n    it 'should extract node visibility' do\n      expect(@session.first('//a')).to be_visible\n\n      expect(@session.find('//div[@id=\"hidden\"]')).not_to be_visible\n      expect(@session.find('//div[@id=\"hidden_via_ancestor\"]')).not_to be_visible\n      expect(@session.find('//div[@id=\"hidden_attr\"]')).not_to be_visible\n      expect(@session.find('//a[@id=\"hidden_attr_via_ancestor\"]')).not_to be_visible\n      expect(@session.find('//input[@id=\"hidden_input\"]')).not_to be_visible\n    end\n\n    it 'template elements should not be visible' do\n      expect(@session.find('//template')).not_to be_visible\n    end\n\n    it 'should be boolean' do\n      expect(@session.first('//a').visible?).to be true\n      expect(@session.find('//div[@id=\"hidden\"]').visible?).to be false\n    end\n\n    it 'closed details > summary elements and descendants should be visible' do\n      expect(@session.find(:css, '#closed_details summary')).to be_visible\n      expect(@session.find(:css, '#closed_details summary h6')).to be_visible\n    end\n\n    it 'details non-summary descendants should be non-visible when closed' do\n      descendants = @session.all(:css, '#closed_details > *:not(summary), #closed_details > *:not(summary) *', minimum: 2)\n      expect(descendants).not_to include(be_visible)\n    end\n\n    it 'deatils descendants should be visible when open' do\n      descendants = @session.all(:css, '#open_details *')\n      expect(descendants).to all(be_visible)\n    end\n\n    it 'works when details is toggled open and closed' do\n      @session.find(:css, '#closed_details > summary').click\n      expect(@session).to have_css('#closed_details *', visible: :visible, count: 5)\n        .and(have_no_css('#closed_details *', visible: :hidden))\n\n      @session.find(:css, '#closed_details > summary').click\n      descendants_css = '#closed_details > *:not(summary), #closed_details > *:not(summary) *'\n      expect(@session).to have_no_css(descendants_css, visible: :visible)\n        .and(have_css(descendants_css, visible: :hidden, count: 3))\n      sleep 20\n    end\n\n    it 'works with popover attribute' do\n      expect(@session.find(:button, 'Should not be clickable')).not_to be_visible\n      expect(@session.find(:button, 'Should be clickable')).not_to be_visible\n      @session.click_button('Show popover')\n      expect(@session.find(:button, 'Should be clickable')).to be_visible\n      expect(@session.find(:button, 'Should not be clickable')).not_to be_visible\n    end\n\n    it 'works with popover parents' do\n      expect(@session.find(:id, 'popover_parent')).not_to be_visible\n      expect(@session.find(:id, 'popover_child')).not_to be_visible\n      @session.click_button('Show parent popover')\n      expect(@session.find(:id, 'popover_child', text: 'Popover Contents')).to be_visible\n    end\n  end\n\n  describe '#obscured?', requires: [:css] do\n    it 'should see non visible elements as obscured' do\n      Capybara.ignore_hidden_elements = false\n      expect(@session.find('//div[@id=\"hidden\"]')).to be_obscured\n      expect(@session.find('//div[@id=\"hidden_via_ancestor\"]')).to be_obscured\n      expect(@session.find('//div[@id=\"hidden_attr\"]')).to be_obscured\n      expect(@session.find('//a[@id=\"hidden_attr_via_ancestor\"]')).to be_obscured\n      expect(@session.find('//input[@id=\"hidden_input\"]')).to be_obscured\n    end\n\n    it 'should see non-overlapped elements as not obscured' do\n      @session.visit('/obscured')\n      expect(@session.find(:css, '#cover')).not_to be_obscured\n    end\n\n    it 'should see elements only overlapped by descendants as not obscured' do\n      skip 'Fails on CI, unsure why. Needs investigation.' if ENV['CI']\n      expect(@session.first(:css, 'p:not(.para)')).not_to be_obscured\n    end\n\n    it 'should see elements outside the viewport as obscured' do\n      @session.visit('/obscured')\n      off = @session.find(:css, '#offscreen')\n      off_wrapper = @session.find(:css, '#offscreen_wrapper')\n      expect(off).to be_obscured\n      expect(off_wrapper).to be_obscured\n      @session.scroll_to(off_wrapper)\n      expect(off_wrapper).not_to be_obscured\n      expect(off).to be_obscured\n      off_wrapper.scroll_to(off)\n      expect(off).not_to be_obscured\n      expect(off_wrapper).not_to be_obscured\n    end\n\n    it 'should see overlapped elements as obscured' do\n      @session.visit('/obscured')\n      expect(@session.find(:css, '#obscured')).to be_obscured\n    end\n\n    it 'should be boolean' do\n      Capybara.ignore_hidden_elements = false\n      expect(@session.first('//a').obscured?).to be false\n      expect(@session.find('//div[@id=\"hidden\"]').obscured?).to be true\n    end\n\n    it 'should work in frames' do\n      @session.visit('/obscured')\n      frame = @session.find(:css, '#frameOne')\n      @session.within_frame(frame) do\n        div = @session.find(:css, '#divInFrameOne')\n        expect(div).to be_obscured\n        @session.scroll_to div\n        expect(div).not_to be_obscured\n      end\n    end\n\n    it 'should work in nested iframes' do\n      @session.visit('/obscured')\n      frame = @session.find(:css, '#nestedFrames')\n      @session.within_frame(frame) do\n        @session.within_frame(:css, '#childFrame') do\n          gcframe = @session.find(:css, '#grandchildFrame2')\n          @session.within_frame(gcframe) do\n            expect(@session.find(:css, '#divInFrameTwo')).to be_obscured\n          end\n          @session.scroll_to(gcframe)\n          @session.within_frame(gcframe) do\n            expect(@session.find(:css, '#divInFrameTwo')).not_to be_obscured\n          end\n        end\n      end\n    end\n  end\n\n  describe '#checked?' do\n    it 'should extract node checked state' do\n      @session.visit('/form')\n      expect(@session.find('//input[@id=\"gender_female\"]')).to be_checked\n      expect(@session.find('//input[@id=\"gender_male\"]')).not_to be_checked\n      expect(@session.first('//h1')).not_to be_checked\n    end\n\n    it 'should be boolean' do\n      @session.visit('/form')\n      expect(@session.find('//input[@id=\"gender_female\"]').checked?).to be true\n      expect(@session.find('//input[@id=\"gender_male\"]').checked?).to be false\n      expect(@session.find('//input[@id=\"no_attr_value_checked\"]').checked?).to be true\n    end\n  end\n\n  describe '#selected?' do\n    it 'should extract node selected state' do\n      @session.visit('/form')\n      expect(@session.find('//option[@value=\"en\"]')).to be_selected\n      expect(@session.find('//option[@value=\"sv\"]')).not_to be_selected\n      expect(@session.first('//h1')).not_to be_selected\n    end\n\n    it 'should be boolean' do\n      @session.visit('/form')\n      expect(@session.find('//option[@value=\"en\"]').selected?).to be true\n      expect(@session.find('//option[@value=\"sv\"]').selected?).to be false\n      expect(@session.first('//h1').selected?).to be false\n    end\n  end\n\n  describe '#==' do\n    it 'preserve object identity' do\n      expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands\n      expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/BinaryOperatorWithIdenticalOperands\n      expect(@session.find('//h1').eql?(@session.find('//h1'))).to be false\n    end\n\n    it 'returns false for unrelated object' do\n      expect(@session.find('//h1') == 'Not Capybara::Node::Base').to be false\n    end\n  end\n\n  describe '#path' do\n    # Testing for specific XPaths here doesn't make sense since there\n    # are many that can refer to the same element\n    before do\n      @session.visit('/path')\n    end\n\n    it 'returns xpath which points to itself' do\n      element = @session.find(:link, 'Second Link')\n      expect(@session.find(:xpath, element.path)).to eq(element)\n    end\n\n    it 'reports when element in shadow dom', requires: [:shadow_dom] do\n      @session.visit('/with_js')\n      shadow = @session.find(:css, '#shadow')\n      element = @session.evaluate_script(<<~JS, shadow)\n        (function(root){\n          return root.shadowRoot.querySelector('span');\n        })(arguments[0])\n      JS\n      expect(element.path).to eq '(: Shadow DOM element - no XPath :)'\n    end\n  end\n\n  describe '#trigger', requires: %i[js trigger] do\n    it 'should allow triggering of custom JS events' do\n      @session.visit('/with_js')\n      @session.find(:css, '#with_focus_event').trigger(:focus)\n      expect(@session).to have_css('#focus_event_triggered')\n    end\n  end\n\n  describe '#drag_to', requires: %i[js drag] do\n    it 'should drag and drop an object' do\n      @session.visit('/with_js')\n      element = @session.find('//div[@id=\"drag\"]')\n      target = @session.find('//div[@id=\"drop\"]')\n      element.drag_to(target)\n      expect(@session).to have_xpath('//div[contains(., \"Dropped!\")]')\n    end\n\n    it 'should drag and drop if scrolling is needed' do\n      @session.visit('/with_js')\n      element = @session.find('//div[@id=\"drag_scroll\"]')\n      target = @session.find('//div[@id=\"drop_scroll\"]')\n      element.drag_to(target)\n      expect(@session).to have_xpath('//div[contains(., \"Dropped!\")]')\n    end\n\n    it 'should drag a link' do\n      @session.visit('/with_js')\n      link = @session.find_link('drag_link')\n      target = @session.find(:id, 'drop')\n      link.drag_to target\n      expect(@session).to have_xpath('//div[contains(., \"Dropped!\")]')\n    end\n\n    it 'should work with Dragula' do\n      @session.visit('/with_dragula')\n      @session.within(:css, '#sortable.ready') do\n        src = @session.find('div', text: 'Item 1')\n        target = @session.find('div', text: 'Item 3')\n        src.drag_to target\n        expect(@session).to have_content(/Item 2.*Item 1/, normalize_ws: true)\n      end\n    end\n\n    it 'should work with jsTree' do\n      @session.visit('/with_jstree')\n      @session.within(:css, '#container') do\n        @session.assert_text(/A.*B.*C/m)\n        source = @session.find(:css, '#j1_1_anchor')\n        target = @session.find(:css, '#j1_2_anchor')\n\n        source.drag_to(target)\n\n        @session.assert_no_text(/A.*B.*C/m)\n        @session.assert_text(/B.*C/m)\n      end\n    end\n\n    it 'should simulate a single held down modifier key' do\n      %I[\n        alt\n        ctrl\n        meta\n        shift\n      ].each do |modifier_key|\n        @session.visit('/with_js')\n\n        element = @session.find('//div[@id=\"drag\"]')\n        target = @session.find('//div[@id=\"drop\"]')\n\n        element.drag_to(target, drop_modifiers: modifier_key)\n        expect(@session).to have_css('div.drag_start', exact_text: 'Dragged!')\n        expect(@session).to have_xpath(\"//div[contains(., 'Dropped!-#{modifier_key}')]\")\n      end\n    end\n\n    it 'should simulate multiple held down modifier keys' do\n      @session.visit('/with_js')\n\n      element = @session.find('//div[@id=\"drag\"]')\n      target = @session.find('//div[@id=\"drop\"]')\n\n      modifier_keys = %I[alt ctrl meta shift]\n\n      element.drag_to(target, drop_modifiers: modifier_keys)\n      expect(@session).to have_xpath(\"//div[contains(., 'Dropped!-#{modifier_keys.join('-')}')]\")\n    end\n\n    it 'should support key aliases' do\n      { control: :ctrl,\n        command: :meta,\n        cmd: :meta }.each do |(key_alias, key)|\n        @session.visit('/with_js')\n\n        element = @session.find('//div[@id=\"drag\"]')\n        target = @session.find('//div[@id=\"drop\"]')\n\n        element.drag_to(target, drop_modifiers: [key_alias])\n        expect(target).to have_text(\"Dropped!-#{key}\", exact: true)\n      end\n    end\n\n    context 'HTML5', requires: %i[js html5_drag] do\n      it 'should HTML5 drag and drop an object' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        element.drag_to(target)\n        expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/plain drag_html5\")]')\n      end\n\n      it 'should HTML5 drag and drop an object child' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]/p')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        element.drag_to(target)\n        expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/plain drag_html5\")]')\n      end\n\n      it 'should set clientX/Y in dragover events' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        element.drag_to(target)\n        expect(@session).to have_css('div.log', text: /DragOver with client position: [1-9]\\d*,[1-9]\\d*/, count: 2)\n      end\n\n      it 'should preserve clientX/Y from last dragover event' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        element.drag_to(target)\n\n        conditions = %w[DragLeave Drop DragEnd].map do |text|\n          have_css('div.log', text: text)\n        end\n        expect(@session).to(conditions.reduce { |memo, cond| memo.and(cond) })\n\n        # The first \"DragOver\" div is inserted by the last dragover event dispatched\n        drag_over_div = @session.first('//div[@class=\"log\" and starts-with(text(), \"DragOver\")]')\n        position = drag_over_div.text.sub('DragOver ', '')\n\n        expect(@session).to have_css('div.log', text: /DragLeave #{position}/, count: 1)\n        expect(@session).to have_css('div.log', text: /Drop #{position}/, count: 1)\n        expect(@session).to have_css('div.log', text: /DragEnd #{position}/, count: 1)\n      end\n\n      it 'should not HTML5 drag and drop on a non HTML5 drop element' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        target.execute_script(\"$(this).removeClass('drop');\")\n        element.drag_to(target)\n        sleep 1\n        expect(@session).not_to have_xpath('//div[contains(., \"HTML5 Dropped\")]')\n      end\n\n      it 'should HTML5 drag and drop when scrolling needed' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5_scroll\"]')\n        target = @session.find('//div[@id=\"drop_html5_scroll\"]')\n        element.drag_to(target)\n        expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/plain drag_html5_scroll\")]')\n      end\n\n      it 'should drag HTML5 default draggable elements' do\n        @session.visit('/with_js')\n        link = @session.find_link('drag_link_html5')\n        target = @session.find(:id, 'drop_html5')\n        link.drag_to target\n        expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped\")]')\n      end\n\n      it 'should work with SortableJS' do\n        @session.visit('/with_sortable_js')\n        @session.within(:css, '#sortable') do\n          src = @session.find('div', text: 'Item 1')\n          target = @session.find('div', text: 'Item 3')\n          src.drag_to target\n          expect(@session).to have_content(/Item 3.*Item 1/, normalize_ws: true)\n        end\n      end\n\n      it 'should drag HTML5 default draggable element child' do\n        @session.visit('/with_js')\n        source = @session.find_link('drag_link_html5').find(:css, 'p')\n        target = @session.find(:id, 'drop_html5')\n        source.drag_to target\n        expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped\")]')\n      end\n\n      it 'should simulate a single held down modifier key' do\n        %I[alt ctrl meta shift].each do |modifier_key|\n          @session.visit('/with_js')\n\n          element = @session.find('//div[@id=\"drag_html5\"]')\n          target = @session.find('//div[@id=\"drop_html5\"]')\n\n          element.drag_to(target, drop_modifiers: modifier_key)\n\n          expect(@session).to have_css('div.drag_start', exact_text: 'HTML5 Dragged!')\n          expect(@session).to have_xpath(\"//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_key}')]\")\n        end\n      end\n\n      it 'should simulate multiple held down modifier keys' do\n        @session.visit('/with_js')\n\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n\n        modifier_keys = %I[alt ctrl meta shift]\n\n        element.drag_to(target, drop_modifiers: modifier_keys)\n        expect(@session).to have_xpath(\"//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_keys.join('-')}')]\")\n      end\n\n      it 'should support key aliases' do\n        { control: :ctrl,\n          command: :meta,\n          cmd: :meta }.each do |(key_alias, key)|\n          @session.visit('/with_js')\n\n          element = @session.find('//div[@id=\"drag_html5\"]')\n          target = @session.find('//div[@id=\"drop_html5\"]')\n\n          element.drag_to(target, drop_modifiers: [key_alias])\n          expect(target).to have_text(%r{^HTML5 Dropped string: text/plain drag_html5-#{key}$}m, exact: true)\n        end\n      end\n\n      it 'should trigger a dragenter event, before the first dragover event' do\n        @session.visit('/with_js')\n        element = @session.find('//div[@id=\"drag_html5\"]')\n        target = @session.find('//div[@id=\"drop_html5\"]')\n        element.drag_to(target)\n\n        # Events are listed in reverse chronological order\n        expect(@session).to have_text(/DragOver.*DragEnter/m)\n      end\n    end\n  end\n\n  describe 'Element#drop', requires: %i[js html5_drag] do\n    it 'can drop a file' do\n      @session.visit('/with_js')\n      target = @session.find('//div[@id=\"drop_html5\"]')\n      target.drop(\n        with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__)))\n      )\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped file: capybara.jpg\")]')\n    end\n\n    it 'can drop multiple files' do\n      @session.visit('/with_js')\n      target = @session.find('//div[@id=\"drop_html5\"]')\n      target.drop(\n        with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))),\n        with_os_path_separators(File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__)))\n      )\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped file: capybara.jpg\")]')\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped file: test_file.txt\")]')\n    end\n\n    it 'can drop strings' do\n      @session.visit('/with_js')\n      target = @session.find('//div[@id=\"drop_html5\"]')\n      target.drop('text/plain' => 'Some dropped text')\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/plain Some dropped text\")]')\n    end\n\n    it 'can drop a pathname' do\n      @session.visit('/with_js')\n      target = @session.find('//div[@id=\"drop_html5\"]')\n      target.drop(\n        Pathname.new(with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))))\n      )\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped file: capybara.jpg\")]')\n    end\n\n    it 'can drop multiple strings' do\n      @session.visit('/with_js')\n      target = @session.find('//div[@id=\"drop_html5\"]')\n      target.drop('text/plain' => 'Some dropped text', 'text/url' => 'http://www.google.com')\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/plain Some dropped text\")]')\n      expect(@session).to have_xpath('//div[contains(., \"HTML5 Dropped string: text/url http://www.google.com\")]')\n    end\n  end\n\n  describe '#hover', requires: [:hover] do\n    it 'should allow hovering on an element' do\n      @session.visit('/with_hover')\n      expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible\n      @session.find(:css, '.wrapper:not(.scroll_needed)').hover\n      expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible\n    end\n\n    it 'should allow hovering on an element that needs to be scrolled into view' do\n      @session.visit('/with_hover')\n      expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible\n      @session.find(:css, '.wrapper.scroll_needed').hover\n      expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible\n    end\n\n    it 'should hover again after following a link and back' do\n      @session.visit('/with_hover')\n      @session.find(:css, '.wrapper:not(.scroll_needed)').hover\n      @session.click_link('Other hover page')\n      @session.click_link('Go back')\n      @session.find(:css, '.wrapper:not(.scroll_needed)').hover\n      expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible\n    end\n  end\n\n  describe '#click' do\n    it 'should not follow a link if no href' do\n      @session.find(:css, '#link_placeholder').click\n      expect(@session.current_url).to match(%r{/with_html$})\n    end\n\n    it 'should go to the same page if href is blank' do\n      @session.find(:css, '#link_blank_href').click\n      sleep 1\n      expect(@session).to have_current_path('/with_html')\n    end\n\n    it 'should be able to check a checkbox' do\n      @session.visit('form')\n      cbox = @session.find(:checkbox, 'form_terms_of_use')\n      expect(cbox).not_to be_checked\n      cbox.click\n      expect(cbox).to be_checked\n    end\n\n    it 'should be able to uncheck a checkbox' do\n      @session.visit('/form')\n      cbox = @session.find(:checkbox, 'form_pets_dog')\n      expect(cbox).to be_checked\n      cbox.click\n      expect(cbox).not_to be_checked\n    end\n\n    it 'should be able to select a radio button' do\n      @session.visit('/form')\n      radio = @session.find(:radio_button, 'gender_male')\n      expect(radio).not_to be_checked\n      radio.click\n      expect(radio).to be_checked\n    end\n\n    it 'should allow modifiers', requires: [:js] do\n      @session.visit('/with_js')\n      @session.find(:css, '#click-test').click(:shift)\n      expect(@session).to have_link('Has been shift clicked')\n    end\n\n    it 'should allow multiple modifiers', requires: [:js] do\n      @session.visit('with_js')\n      @session.find(:css, '#click-test').click(:control, :alt, :meta, :shift)\n      # Selenium with Chrome on OSX ctrl-click generates a right click so just verify all keys but not click type\n      expect(@session).to have_link('alt control meta shift')\n    end\n\n    it 'should allow to adjust the click offset', requires: [:js] do\n      Capybara.w3c_click_offset = false\n      @session.visit('with_js')\n      @session.find(:css, '#click-test').click(x: 5, y: 5)\n      link = @session.find(:link, 'has-been-clicked')\n      locations = link.text.match(/^Has been clicked at (?<x>[\\d.-]+),(?<y>[\\d.-]+)$/)\n      # Resulting click location should be very close to 0, 0 relative to top left corner of the element, but may not be exact due to\n      # integer/float conversions and rounding.\n      expect(locations[:x].to_f).to be_within(1).of(5)\n      expect(locations[:y].to_f).to be_within(1).of(5)\n    end\n\n    it 'should raise error if both x and y values are not passed' do\n      @session.visit('with_js')\n      el = @session.find(:css, '#click-test')\n      expect { el.click(x: 5) }.to raise_error ArgumentError\n      expect { el.click(x: nil, y: 3) }.to raise_error ArgumentError\n    end\n\n    it 'should be able to click a table row', requires: [:js] do\n      @session.visit('/tables')\n      tr = @session.find(:css, '#agent_table tr:first-child').click\n      expect(tr).to have_css('label', text: 'Clicked')\n    end\n\n    it 'should retry clicking', requires: [:js] do\n      @session.visit('/animated')\n      obscured = @session.find(:css, '#obscured')\n      @session.execute_script <<~JS\n        setTimeout(function(){ $('#cover').hide(); }, 700)\n      JS\n      expect { obscured.click }.not_to raise_error\n    end\n\n    it 'should allow to retry longer', requires: [:js] do\n      @session.visit('/animated')\n      obscured = @session.find(:css, '#obscured')\n      @session.execute_script <<~JS\n        setTimeout(function(){ $('#cover').hide(); }, 3000)\n      JS\n      expect { obscured.click(wait: 4) }.not_to raise_error\n    end\n\n    it 'should not retry clicking when wait is disabled', requires: [:js] do\n      @session.visit('/animated')\n      obscured = @session.find(:css, '#obscured')\n      @session.execute_script <<~JS\n        setTimeout(function(){ $('#cover').hide(); }, 2000)\n      JS\n      expect { obscured.click(wait: 0) }.to(raise_error { |e| expect(e).to be_an_invalid_element_error(@session) })\n    end\n\n    context 'offset', requires: [:js] do\n      before do\n        @session.visit('/offset')\n      end\n\n      let :clicker do\n        @session.find(:id, 'clicker')\n      end\n\n      context 'when w3c_click_offset is false' do\n        before do\n          Capybara.w3c_click_offset = false\n        end\n\n        it 'should offset from top left of element' do\n          clicker.click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 110,105/)\n        end\n\n        it 'should offset outside the element' do\n          clicker.click(x: -15, y: -10)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n\n      context 'when w3c_click_offset is true' do\n        before do\n          Capybara.w3c_click_offset = true\n        end\n\n        it 'should offset from center of element' do\n          clicker.click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 160,155/)\n        end\n\n        it 'should offset outside from center of element' do\n          clicker.click(x: -65, y: -60)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n    end\n\n    context 'delay', requires: [:js] do\n      it 'should delay the mouse up' do\n        @session.visit('with_js')\n        @session.find(:css, '#click-test').click(delay: 2)\n        delay = @session.evaluate_script('window.click_delay')\n        expect(delay).to be >= 2\n      end\n    end\n  end\n\n  describe '#double_click', requires: [:js] do\n    it 'should double click an element' do\n      @session.visit('/with_js')\n      @session.find(:css, '#click-test').double_click\n      expect(@session.find(:css, '#has-been-double-clicked')).to be_truthy\n    end\n\n    it 'should allow modifiers', requires: [:js] do\n      @session.visit('/with_js')\n      @session.find(:css, '#click-test').double_click(:alt)\n      expect(@session).to have_link('Has been alt double clicked')\n    end\n\n    it 'should allow to adjust the offset', requires: [:js] do\n      Capybara.w3c_click_offset = false\n      @session.visit('with_js')\n      @session.find(:css, '#click-test').double_click(x: 10, y: 5)\n      link = @session.find(:link, 'has-been-double-clicked')\n      locations = link.text.match(/^Has been double clicked at (?<x>[\\d.-]+),(?<y>[\\d.-]+)$/)\n      # Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due\n      # to integer/float conversions and rounding.\n      expect(locations[:x].to_f).to be_within(1).of(10)\n      expect(locations[:y].to_f).to be_within(1).of(5)\n    end\n\n    it 'should retry clicking', requires: [:js] do\n      @session.visit('/animated')\n      obscured = @session.find(:css, '#obscured')\n      @session.execute_script <<~JS\n        setTimeout(function(){ $('#cover').hide(); }, 700)\n      JS\n      expect { obscured.double_click }.not_to raise_error\n    end\n\n    context 'offset', requires: [:js] do\n      before do\n        @session.visit('/offset')\n      end\n\n      let :clicker do\n        @session.find(:id, 'clicker')\n      end\n\n      context 'when w3c_click_offset is false' do\n        before do\n          Capybara.w3c_click_offset = false\n        end\n\n        it 'should offset from top left of element' do\n          clicker.double_click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 110,105/)\n        end\n\n        it 'should offset outside the element' do\n          clicker.double_click(x: -15, y: -10)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.double_click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n\n      context 'when w3c_click_offset is true' do\n        before do\n          Capybara.w3c_click_offset = true\n        end\n\n        it 'should offset from center of element' do\n          clicker.double_click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 160,155/)\n        end\n\n        it 'should offset outside from center of element' do\n          clicker.double_click(x: -65, y: -60)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.double_click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n    end\n  end\n\n  describe '#right_click', requires: [:js] do\n    it 'should right click an element' do\n      @session.visit('/with_js')\n      @session.find(:css, '#click-test').right_click\n      expect(@session.find(:css, '#has-been-right-clicked')).to be_truthy\n    end\n\n    it 'should allow modifiers', requires: [:js] do\n      @session.visit('/with_js')\n      @session.find(:css, '#click-test').right_click(:meta)\n      expect(@session).to have_link('Has been meta right clicked')\n    end\n\n    it 'should allow to adjust the offset', requires: [:js] do\n      Capybara.w3c_click_offset = false\n      @session.visit('with_js')\n      @session.find(:css, '#click-test').right_click(x: 10, y: 10)\n      link = @session.find(:link, 'has-been-right-clicked')\n      locations = link.text.match(/^Has been right clicked at (?<x>[\\d.-]+),(?<y>[\\d.-]+)$/)\n      # Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due\n      # to integer/float conversions and rounding\n      expect(locations[:x].to_f).to be_within(1).of(10)\n      expect(locations[:y].to_f).to be_within(1).of(10)\n    end\n\n    it 'should retry clicking', requires: [:js] do\n      @session.visit('/animated')\n      obscured = @session.find(:css, '#obscured')\n      @session.execute_script <<~JS\n        setTimeout(function(){ $('#cover').hide(); }, 700)\n      JS\n      expect { obscured.right_click }.not_to raise_error\n    end\n\n    context 'offset', requires: [:js] do\n      before do\n        @session.visit('/offset')\n      end\n\n      let :clicker do\n        @session.find(:id, 'clicker')\n      end\n\n      context 'when w3c_click_offset is false' do\n        before do\n          Capybara.w3c_click_offset = false\n        end\n\n        it 'should offset from top left of element' do\n          clicker.right_click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 110,105/)\n        end\n\n        it 'should offset outside the element' do\n          clicker.right_click(x: -15, y: -10)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.right_click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n\n      context 'when w3c_click_offset is true' do\n        before do\n          Capybara.w3c_click_offset = true\n        end\n\n        it 'should offset from center of element' do\n          clicker.right_click(x: 10, y: 5)\n          expect(@session).to have_text(/clicked at 160,155/)\n        end\n\n        it 'should offset outside from center of element' do\n          clicker.right_click(x: -65, y: -60)\n          expect(@session).to have_text(/clicked at 85,90/)\n        end\n\n        it 'should default to click the middle' do\n          clicker.right_click\n          expect(@session).to have_text(/clicked at 150,150/)\n        end\n      end\n    end\n\n    context 'delay', requires: [:js] do\n      it 'should delay the mouse up' do\n        @session.visit('with_js')\n        @session.find(:css, '#click-test').right_click(delay: 2)\n        delay = @session.evaluate_script('window.right_click_delay')\n        expect(delay).to be >= 2\n      end\n    end\n  end\n\n  describe '#send_keys', requires: [:send_keys] do\n    it 'should send a string of keys to an element' do\n      @session.visit('/form')\n      @session.find(:css, '#address1_city').send_keys('Oceanside')\n      expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'\n    end\n\n    it 'should send special characters' do\n      @session.visit('/form')\n      @session.find(:css, '#address1_city').send_keys('Ocean', :space, 'sie', :left, 'd')\n      expect(@session.find(:css, '#address1_city').value).to eq 'Ocean side'\n    end\n\n    it 'should allow for multiple simultaneous keys' do\n      @session.visit('/form')\n      @session.find(:css, '#address1_city').send_keys([:shift, 'o'], 'ceanside')\n      expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'\n    end\n\n    it 'should hold modifiers at top level' do\n      @session.visit('/form')\n      @session.find(:css, '#address1_city').send_keys('ocean', :shift, 'side')\n      expect(@session.find(:css, '#address1_city').value).to eq 'oceanSIDE'\n    end\n\n    it 'should generate key events', requires: %i[send_keys js] do\n      @session.visit('/with_js')\n      @session.find(:css, '#with-key-events').send_keys([:shift, 't'], [:shift, 'w'])\n      expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:84 keydown:16 keydown:87')\n    end\n  end\n\n  describe '#execute_script', requires: %i[js es_args] do\n    it 'should execute the given script in the context of the element and return nothing' do\n      @session.visit('/with_js')\n      expect(@session.find(:css, '#change').execute_script(\"this.textContent = 'Funky Doodle'\")).to be_nil\n      expect(@session).to have_css('#change', text: 'Funky Doodle')\n    end\n\n    it 'should pass arguments to the script' do\n      @session.visit('/with_js')\n      @session.find(:css, '#change').execute_script('this.textContent = arguments[0]', 'Doodle Funk')\n      expect(@session).to have_css('#change', text: 'Doodle Funk')\n    end\n  end\n\n  describe '#evaluate_script', requires: %i[js es_args] do\n    it 'should evaluate the given script in the context of the element and return whatever it produces' do\n      @session.visit('/with_js')\n      el = @session.find(:css, '#with_change_event')\n      expect(el.evaluate_script('this.value')).to eq('default value')\n    end\n\n    it 'should ignore leading whitespace' do\n      @session.visit('/with_js')\n      expect(@session.find(:css, '#change').evaluate_script('\n        2 + 3\n      ')).to eq 5\n    end\n\n    it 'should pass arguments to the script' do\n      @session.visit('/with_js')\n      @session.find(:css, '#change').evaluate_script('this.textContent = arguments[0]', 'Doodle Funk')\n      expect(@session).to have_css('#change', text: 'Doodle Funk')\n    end\n\n    it 'should pass multiple arguments' do\n      @session.visit('/with_js')\n      change = @session.find(:css, '#change')\n      expect(change.evaluate_script('arguments[0] + arguments[1]', 2, 3)).to eq 5\n    end\n\n    it 'should support returning elements' do\n      @session.visit('/with_js')\n      change = @session.find(:css, '#change') # ensure page has loaded and element is available\n      el = change.evaluate_script('this')\n      expect(el).to be_instance_of(Capybara::Node::Element)\n      expect(el).to eq(change)\n    end\n\n    it 'should support multiple statements via IIFE' do\n      @session.visit('/with_js')\n      change = @session.find(:css, '#change') # ensure page has loaded and element is available\n      res = change.evaluate_script(<<~JS, 3)\n        (function(n){\n          var el = this;\n          return [el, n];\n        }).apply(this, arguments)\n      JS\n      expect(res).to eq [change, 3]\n    end\n  end\n\n  describe '#evaluate_async_script', requires: %i[js es_args] do\n    it 'should evaluate the given script in the context of the element' do\n      @session.visit('/with_js')\n      el = @session.find(:css, '#with_change_event')\n      expect(el.evaluate_async_script('arguments[0](this.value)')).to eq('default value')\n    end\n\n    it 'should support returning elements after asynchronous operation' do\n      @session.visit('/with_js')\n      change = @session.find(:css, '#change') # ensure page has loaded and element is available\n      el = change.evaluate_async_script('var cb = arguments[0]; setTimeout(function(el){ cb(el) }, 100, this)')\n      expect(el).to eq(change)\n    end\n  end\n\n  describe '#shadow_root', requires: %i[js] do\n    it 'should get the shadow root' do\n      @session.visit('/with_shadow')\n      expect do\n        shadow_root = @session.find(:css, '#shadow_host').shadow_root\n        expect(shadow_root).to be_a(Capybara::Node::Element)\n      end.not_to raise_error\n    end\n\n    it 'should find elements inside the shadow dom using CSS' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      expect(shadow_root).to have_css('#shadow_content', text: 'some text')\n    end\n\n    it 'should find nested shadow roots' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      nested_shadow_root = shadow_root.find(:css, '#nested_shadow_host').shadow_root\n      expect(nested_shadow_root).to have_css('#nested_shadow_content', text: 'nested text')\n    end\n\n    it 'should click on elements' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      checkbox = shadow_root.find(:css, 'input[type=\"checkbox\"]')\n      expect(checkbox).not_to be_checked\n      checkbox.click\n      expect(checkbox).to be_checked\n    end\n\n    it 'should use convenience methods once moved to a descendant of the shadow root' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      descendant = shadow_root.find(:css, '#controls_wrapper')\n      expect do\n        descendant.check('shadow_checkbox')\n      end.not_to raise_error\n      expect(descendant).to have_checked_field('shadow_checkbox')\n    end\n\n    it 'should produce error messages when failing' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      expect do\n        expect(shadow_root).to have_css('#shadow_content', text: 'Not in the document')\n      end.to raise_error(/tag=\"ShadowRoot\"/)\n    end\n\n    it 'should get visible text' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      expect(shadow_root).to have_text('some text scroll.html')\n    end\n\n    it 'should get all text' do\n      @session.visit('/with_shadow')\n      shadow_root = @session.find(:css, '#shadow_host').shadow_root\n      expect(shadow_root).to have_text(:all, 'some text scroll.html')\n    end\n  end\n\n  describe '#reload', requires: [:js] do\n    it 'should reload elements found via ancestor with CSS' do\n      @session.visit('/with_js')\n      node = @session.find(:css, '#reload-me em').ancestor(:css, 'div')\n      node.reload\n      expect(node[:id]).to eq 'reload-me'\n    end\n\n    it 'should reload elements found via ancestor with XPath' do\n      @session.visit('/with_js')\n      node = @session.find(:css, '#reload-me em').ancestor(:xpath, './/div')\n      node.reload\n      expect(node[:id]).to eq 'reload-me'\n    end\n\n    it 'should reload elements found via sibling' do\n      @session.visit('/with_js')\n      node = @session.find(:css, '#the-list li', text: 'Item 1').sibling(:css, 'li')\n      expect(node.text).to eq 'Item 2'\n      node.reload\n      expect(node.text).to eq 'Item 2'\n    end\n\n    context 'without automatic reload' do\n      before { Capybara.automatic_reload = false }\n\n      after { Capybara.automatic_reload = true }\n\n      it 'should reload the current context of the node' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me')\n        @session.click_link('Reload!')\n        sleep(0.3)\n        expect(node.reload.text).to eq('has been reloaded')\n        expect(node.text).to eq('has been reloaded')\n      end\n\n      it 'should reload a parent node' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me').find(:css, 'em')\n        @session.click_link('Reload!')\n        sleep(0.3)\n        expect(node.reload.text).to eq('has been reloaded')\n        expect(node.text).to eq('has been reloaded')\n      end\n\n      it 'should not automatically reload' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me')\n        @session.click_link('Reload!')\n        sleep(0.3)\n        expect do\n          expect(node).to have_text('has been reloaded')\n        end.to(raise_error do |error|\n          expect(error).to be_an_invalid_element_error(@session)\n        end)\n      end\n    end\n\n    context 'with automatic reload' do\n      before do\n        Capybara.default_max_wait_time = 4\n      end\n\n      it 'should reload the current context of the node automatically' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me')\n        @session.click_link('Reload!')\n        sleep(1)\n        expect(node.text).to eq('has been reloaded')\n      end\n\n      it 'should reload a parent node automatically' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me').find(:css, 'em')\n        @session.click_link('Reload!')\n        sleep(1)\n        expect(node.text).to eq('has been reloaded')\n      end\n\n      it 'should reload a node automatically when using find' do\n        @session.visit('/with_js')\n        node = @session.find(:css, '#reload-me')\n        @session.click_link('Reload!')\n        sleep(1)\n        expect(node.find(:css, 'a').text).to eq('has been reloaded')\n      end\n\n      it \"should not reload nodes which haven't been found with reevaluateable queries\" do\n        @session.visit('/with_js')\n        node = @session.all(:css, '#the-list li')[1]\n        @session.click_link('Fetch new list!')\n        sleep(1)\n\n        expect do\n          expect(node).to have_text('Foo')\n        end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })\n        expect do\n          expect(node).to have_text('Bar')\n        end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })\n      end\n\n      it 'should reload nodes with options' do\n        @session.visit('/with_js')\n        node = @session.find(:css, 'em', text: 'reloaded')\n        @session.click_link('Reload!')\n        sleep(1)\n        expect(node.text).to eq('has been reloaded')\n      end\n    end\n  end\n\n  context 'when #synchronize raises server errors' do\n    it 'sets an explanatory exception as the cause of server exceptions', requires: %i[server js] do\n      quietly { @session.visit('/error') }\n      expect do\n        @session.find(:css, 'span')\n      end.to(raise_error(TestApp::TestAppError) do |e|\n        expect(e.cause).to be_a Capybara::CapybaraError\n        expect(e.cause.message).to match(/Your application server raised an error/)\n      end)\n    end\n\n    it 'sets an explanatory exception as the cause of server exceptions with errors with initializers', requires: %i[server js] do\n      quietly { @session.visit('/other_error') }\n      expect do\n        @session.find(:css, 'span')\n      end.to(raise_error(TestApp::TestAppOtherError) do |e|\n        expect(e.cause).to be_a Capybara::CapybaraError\n        expect(e.cause.message).to match(/Your application server raised an error/)\n      end)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/node_wrapper_spec.rb",
    "content": "# frozen_string_literal: true\n\nclass NodeWrapper\n  def initialize(element); @element = element end\n  def to_capybara_node(); @element end\nend\n\nCapybara::SpecHelper.spec '#to_capybara_node' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  it 'should support have_xxx expectations' do\n    para = NodeWrapper.new(@session.find(:css, '#first'))\n    expect(para).to have_link('ullamco')\n  end\n\n  it 'should support within' do\n    para = NodeWrapper.new(@session.find(:css, '#first'))\n    expect(@session).to have_css('#second')\n    @session.within(para) do\n      expect(@session).to have_link('ullamco')\n      expect(@session).not_to have_css('#second')\n    end\n  end\n\n  it 'should generate correct errors' do\n    para = NodeWrapper.new(@session.find(:css, '#first'))\n    expect do\n      expect(para).to have_text('Header Class Test One')\n    end.to raise_error(/^expected to find text \"Header Class Test One\" in \"Lore/)\n    expect do\n      expect(para).to have_css('#second')\n    end.to raise_error(/^expected to find css \"#second\" within #<Capybara::Node::Element/)\n    expect do\n      expect(para).to have_link(href: %r{/without_simple_html})\n    end.to raise_error(%r{^expected to find link with href matching /\\\\/without_simple_html/ within #<Capybara::Node::Element})\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/refresh_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec '#refresh' do\n  it 'reload the page' do\n    @session.visit('/form')\n    expect(@session).to have_select('form_locale', selected: 'English')\n    @session.select('Swedish', from: 'form_locale')\n    expect(@session).to have_select('form_locale', selected: 'Swedish')\n    @session.refresh\n    expect(@session).to have_select('form_locale', selected: 'English')\n  end\n\n  it 'raises any errors caught inside the server', requires: [:server] do\n    quietly { @session.visit('/error') }\n    expect do\n      @session.refresh\n    end.to raise_error(TestApp::TestAppError)\n  end\n\n  it 'it reposts' do\n    @session.visit('/form')\n    @session.select('Sweden', from: 'form_region')\n    @session.click_button('awesome')\n    sleep 2\n    expect do\n      @session.refresh\n      sleep 2\n    end.to change { extract_results(@session)['post_count'] }.by(1)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/reset_session_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#reset_session!' do\n  it 'removes cookies from current domain' do\n    @session.visit('/set_cookie')\n    @session.visit('/get_cookie')\n    expect(@session).to have_content('test_cookie')\n\n    @session.reset_session!\n    @session.visit('/get_cookie')\n    expect(@session.body).not_to include('test_cookie')\n  end\n\n  it 'removes ALL cookies', requires: [:server] do\n    domains = ['localhost', '127.0.0.1']\n    domains.each do |domain|\n      @session.visit(\"http://#{domain}:#{@session.server.port}/set_cookie\")\n      @session.visit(\"http://#{domain}:#{@session.server.port}/get_cookie\")\n      expect(@session).to have_content('test_cookie')\n    end\n    @session.reset_session!\n    domains.each do |domain|\n      @session.visit(\"http://#{domain}:#{@session.server.port}/get_cookie\")\n      expect(@session.body).not_to include('test_cookie')\n    end\n  end\n\n  it 'resets current url, host, path' do\n    @session.visit '/foo'\n    expect(@session.current_url).not_to be_empty\n    expect(@session.current_host).not_to be_empty\n    expect(@session.current_path).to eq('/foo')\n\n    @session.reset_session!\n    expect(@session.current_url).to satisfy('be a blank url') { |url| [nil, '', 'about:blank'].include? url }\n    expect(@session.current_path).to satisfy('be a blank path') { |path| ['', nil].include? path }\n    expect(@session.current_host).to be_nil\n  end\n\n  it 'resets page body' do\n    @session.visit('/with_html')\n    expect(@session).to have_content('This is a test')\n    expect(@session.find('.//h1').text).to include('This is a test')\n\n    @session.reset_session!\n    expect(@session.body).not_to include('This is a test')\n    expect(@session).to have_no_selector('.//h1')\n  end\n\n  it 'is synchronous' do\n    @session.visit('/with_slow_unload')\n    expect(@session).to have_selector(:css, 'div')\n    @session.reset_session!\n    expect(@session).to have_no_selector :xpath, '/html/body/*', wait: false\n  end\n\n  it 'handles modals during unload', requires: [:modals] do\n    @session.visit('/with_unload_alert')\n    expect(@session).to have_selector(:css, 'div')\n    expect { @session.reset_session! }.not_to raise_error\n    expect(@session).to have_no_selector :xpath, '/html/body/*', wait: false\n  end\n\n  it 'handles already open modals', requires: [:modals] do\n    @session.visit('/with_unload_alert')\n    @session.click_link('Go away')\n    expect { @session.reset_session! }.not_to raise_error\n    expect(@session).to have_no_selector :xpath, '/html/body/*', wait: false\n  end\n\n  it 'raises any standard errors caught inside the server', requires: [:server] do\n    quietly { @session.visit('/error') }\n    expect do\n      @session.reset_session!\n    end.to raise_error(TestApp::TestAppError)\n    @session.visit('/')\n    expect(@session.current_path).to eq('/')\n  end\n\n  it 'closes extra windows', requires: [:windows] do\n    @session.visit('/with_html')\n    @session.open_new_window\n    @session.open_new_window\n    expect(@session.windows.size).to eq 3\n    @session.reset_session!\n    expect(@session.windows.size).to eq 1\n  end\n\n  it 'closes extra windows when not on the first window', requires: [:windows] do\n    @session.visit('/with_html')\n    @session.switch_to_window(@session.open_new_window)\n    @session.open_new_window\n    expect(@session.windows.size).to eq 3\n    @session.reset_session!\n    expect(@session.windows.size).to eq 1\n  end\n\n  it 'does not block opening a new window after a frame was switched to and not switched back', requires: [:windows] do\n    @session.visit('/with_iframe?id=test_iframe&url=/')\n    @session.switch_to_frame(@session.find(:frame, 'test_iframe'))\n    within_window_test = lambda do\n      @session.within_window(@session.open_new_window) do\n        @session.visit('/')\n      end\n    end\n    expect(&within_window_test).to raise_error(Capybara::ScopeError)\n    @session.reset_session!\n    expect(&within_window_test).not_to raise_error\n  end\n\n  context 'When reuse_server == false' do\n    let!(:orig_reuse_server) { Capybara.reuse_server }\n\n    before do\n      Capybara.reuse_server = false\n    end\n\n    after do\n      Capybara.reuse_server = orig_reuse_server\n    end\n\n    it 'raises any standard errors caught inside the server during a second session', requires: [:server] do\n      Capybara.using_driver(@session.mode) do\n        Capybara.using_session(:another_session) do\n          another_session = Capybara.current_session\n          quietly { another_session.visit('/error') }\n          expect do\n            another_session.reset_session!\n          end.to raise_error(TestApp::TestAppError)\n          another_session.visit('/')\n          expect(another_session.current_path).to eq('/')\n        end\n      end\n    end\n  end\n\n  it 'raises configured errors caught inside the server', requires: [:server] do\n    prev_errors = Capybara.server_errors.dup\n\n    Capybara.server_errors = [LoadError]\n    quietly { @session.visit('/error') }\n    expect do\n      @session.reset_session!\n    end.not_to raise_error\n\n    quietly { @session.visit('/load_error') }\n    expect do\n      @session.reset_session!\n    end.to raise_error(LoadError)\n\n    Capybara.server_errors = prev_errors\n  end\n\n  it 'ignores server errors when `Capybara.raise_server_errors = false`', requires: [:server] do\n    Capybara.raise_server_errors = false\n    quietly { @session.visit('/error') }\n    @session.reset_session!\n    @session.visit('/')\n    expect(@session.current_path).to eq('/')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/response_code_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#status_code' do\n  it 'should return response codes', requires: [:status_code] do\n    @session.visit('/with_simple_html')\n    expect(@session.status_code).to eq(200)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/save_and_open_page_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'launchy'\n\nCapybara::SpecHelper.spec '#save_and_open_page' do\n  before do\n    @session.visit '/foo'\n  end\n\n  after do\n    Dir.glob('capybara-*.html').each do |file|\n      FileUtils.rm(file)\n    end\n  end\n\n  it 'sends open method to launchy' do\n    allow(Launchy).to receive(:open)\n    @session.save_and_open_page\n    expect(Launchy).to have_received(:open).with(/capybara-\\d+\\.html/)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/save_and_open_screenshot_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'launchy'\n\nCapybara::SpecHelper.spec '#save_and_open_screenshot' do\n  before do\n    @session.visit '/'\n  end\n\n  it 'opens file from the default directory', requires: [:screenshot] do\n    expected_file_regex = /capybara-\\d+\\.png/\n    allow(@session.driver).to receive(:save_screenshot)\n    allow(Launchy).to receive(:open)\n\n    @session.save_and_open_screenshot\n\n    expect(@session.driver).to have_received(:save_screenshot)\n      .with(expected_file_regex, any_args)\n    expect(Launchy).to have_received(:open).with(expected_file_regex)\n  end\n\n  it 'opens file from the provided directory', requires: [:screenshot] do\n    custom_path = 'screenshots/1.png'\n    allow(@session.driver).to receive(:save_screenshot)\n    allow(Launchy).to receive(:open)\n\n    @session.save_and_open_screenshot(custom_path)\n\n    expect(@session.driver).to have_received(:save_screenshot)\n      .with(/#{custom_path}$/, any_args)\n    expect(Launchy).to have_received(:open).with(/#{custom_path}$/)\n  end\n\n  context 'when launchy cannot be required' do\n    it 'prints out a correct warning message', requires: [:screenshot] do\n      file_path = File.join(Dir.tmpdir, 'test.png')\n      allow(@session).to receive(:warn)\n      allow(@session).to receive(:require).with('launchy').and_raise(LoadError)\n      @session.save_and_open_screenshot(file_path)\n      expect(@session).to have_received(:warn).with(\"File saved to #{file_path}.\\nPlease install the launchy gem to open the file automatically.\")\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/save_page_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#save_page' do\n  let(:alternative_path) { File.join(Dir.pwd, 'save_and_open_page_tmp') }\n  before do\n    @old_save_path = Capybara.save_path\n    Capybara.save_path = nil\n    @session.visit('/foo')\n  end\n\n  after do\n    Capybara.save_path = @old_save_path\n    Dir.glob('capybara-*.html').each do |file|\n      FileUtils.rm(file)\n    end\n    FileUtils.rm_rf alternative_path\n  end\n\n  it 'saves the page in the root directory' do\n    @session.save_page\n    path = Dir.glob('capybara-*.html').first\n    expect(File.read(path)).to include('Another World')\n  end\n\n  it 'generates a sensible filename' do\n    @session.save_page\n    filename = Dir.glob('capybara-*.html').first\n    expect(filename).to match(/^capybara-\\d+\\.html$/)\n  end\n\n  it 'can store files in a specified directory' do\n    Capybara.save_path = alternative_path\n    @session.save_page\n    path = Dir.glob(\"#{alternative_path}/capybara-*.html\").first\n    expect(File.read(path)).to include('Another World')\n  end\n\n  it 'uses the given filename' do\n    @session.save_page('capybara-001122.html')\n    expect(File.read('capybara-001122.html')).to include('Another World')\n  end\n\n  it 'can store files in a specified directory with a given filename' do\n    Capybara.save_path = alternative_path\n    @session.save_page('capybara-001133.html')\n    path = \"#{alternative_path}/capybara-001133.html\"\n    expect(File.read(path)).to include('Another World')\n  end\n\n  it 'can store files in a specified directory with a given relative filename' do\n    Capybara.save_path = alternative_path\n    @session.save_page('tmp/capybara-001144.html')\n    path = \"#{alternative_path}/tmp/capybara-001144.html\"\n    expect(File.read(path)).to include('Another World')\n  end\n\n  it 'returns an absolute path in pwd' do\n    result = @session.save_page\n    path = File.expand_path(Dir.glob('capybara-*.html').first, Dir.pwd)\n    expect(result).to eq(path)\n  end\n\n  it 'returns an absolute path in given directory' do\n    Capybara.save_path = alternative_path\n    result = @session.save_page\n    path = File.expand_path(Dir.glob(\"#{alternative_path}/capybara-*.html\").first, alternative_path)\n    expect(result).to eq(path)\n  end\n\n  context 'asset_host contains a string' do\n    before { Capybara.asset_host = 'http://example.com' }\n\n    after { Capybara.asset_host = nil }\n\n    it 'prepends base tag with value from asset_host to the head' do\n      @session.visit('/with_js')\n      path = @session.save_page\n\n      result = File.read(path)\n      expect(result).to include(\"<head><base href='http://example.com' />\")\n    end\n\n    it \"doesn't prepend base tag to pages when asset_host is nil\" do\n      Capybara.asset_host = nil\n      @session.visit('/with_js')\n      path = @session.save_page\n\n      result = File.read(path)\n      expect(result).to include('<html')\n      expect(result).not_to include('http://example.com')\n    end\n\n    it \"doesn't prepend base tag to pages which already have it\" do\n      @session.visit('/with_base_tag')\n      path = @session.save_page\n\n      result = File.read(path)\n      expect(result).to include('<html')\n      expect(result).not_to include('http://example.com')\n    end\n\n    it 'executes successfully even if the page is missing a <head>' do\n      @session.visit('/with_simple_html')\n      path = @session.save_page\n\n      result = File.read(path)\n      expect(result).to include('Bar')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/save_screenshot_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do\n  let(:alternative_path) { File.join(Dir.pwd, 'save_screenshot_tmp') }\n  before do\n    @old_save_path = Capybara.save_path\n    Capybara.save_path = nil\n    @session.visit '/foo'\n  end\n\n  after do\n    Capybara.save_path = @old_save_path\n    FileUtils.rm_rf alternative_path\n  end\n\n  it 'generates sensible filename' do\n    allow(@session.driver).to receive(:save_screenshot)\n\n    @session.save_screenshot\n\n    regexp = Regexp.new(File.join(Dir.pwd, 'capybara-\\d+\\.png'))\n    expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)\n  end\n\n  it 'allows to specify another path' do\n    allow(@session.driver).to receive(:save_screenshot)\n\n    custom_path = 'screenshots/1.png'\n    @session.save_screenshot(custom_path)\n\n    expect(@session.driver).to have_received(:save_screenshot).with(/#{custom_path}$/, any_args)\n  end\n\n  context 'with Capybara.save_path' do\n    it 'file is generated in the correct location' do\n      Capybara.save_path = alternative_path\n      allow(@session.driver).to receive(:save_screenshot)\n\n      @session.save_screenshot\n\n      regexp = Regexp.new(File.join(alternative_path, 'capybara-\\d+\\.png'))\n      expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)\n    end\n\n    it 'relative paths are relative to save_path' do\n      Capybara.save_path = alternative_path\n      allow(@session.driver).to receive(:save_screenshot)\n\n      custom_path = 'screenshots/2.png'\n      @session.save_screenshot(custom_path)\n\n      expect(@session.driver).to have_received(:save_screenshot).with(File.expand_path(custom_path, alternative_path), any_args)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/screenshot_spec.rb",
    "content": "# coding: US-ASCII\n# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#save_screenshot' do\n  let(:image_path) { File.join(Dir.tmpdir, 'capybara-screenshot.png') }\n\n  before do\n    @session.visit '/'\n  end\n\n  it 'should generate PNG file', requires: [:screenshot] do\n    path = @session.save_screenshot image_path\n\n    magic = File.read(image_path, 4)\n    expect(magic).to eq \"\\x89PNG\"\n    expect(path).to eq image_path\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/scroll_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#scroll_to', requires: [:scroll] do\n  before do\n    @session.visit('/scroll')\n  end\n\n  it 'can scroll an element to the top of the viewport' do\n    el = @session.find(:css, '#scroll')\n    @session.scroll_to(el, align: :top)\n    expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(1).of(0)\n  end\n\n  it 'can scroll an element to the bottom of the viewport' do\n    el = @session.find(:css, '#scroll')\n    @session.scroll_to(el, align: :bottom)\n    el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')\n    viewport_bottom = el.evaluate_script('document.documentElement.clientHeight')\n    expect(el_bottom).to be_within(1).of(viewport_bottom)\n  end\n\n  it 'can scroll an element to the center of the viewport' do\n    el = @session.find(:css, '#scroll')\n    @session.scroll_to(el, align: :center)\n    el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')\n    viewport_bottom = el.evaluate_script('document.documentElement.clientHeight')\n    expect(el_center).to be_within(2).of(viewport_bottom / 2)\n  end\n\n  it 'can scroll the window to the vertical top' do\n    @session.scroll_to :bottom\n    @session.scroll_to :top\n    expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, 0]\n  end\n\n  it 'can scroll the window to the vertical bottom' do\n    @session.scroll_to :bottom\n    max_scroll = @session.evaluate_script('document.documentElement.scrollHeight - document.documentElement.clientHeight')\n    scrolled_location_x, scrolled_location_y = @session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')\n    expect(scrolled_location_x).to be_within(0.5).of(0)\n    expect(scrolled_location_y).to be_within(0.5).of(max_scroll)\n  end\n\n  it 'can scroll the window to the vertical center' do\n    @session.scroll_to :center\n    max_scroll = @session.evaluate_script('document.documentElement.scrollHeight - document.documentElement.clientHeight')\n    expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to match [0, be_within(1).of(max_scroll / 2)]\n  end\n\n  it 'can scroll the window to specific location' do\n    @session.scroll_to 100, 100\n    expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [100, 100]\n  end\n\n  it 'can scroll an element to the top of the scrolling element' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    el = scrolling_element.find(:css, '#inner')\n    scrolling_element.scroll_to(el, align: :top)\n    scrolling_element_top = scrolling_element.evaluate_script('this.getBoundingClientRect().top')\n    expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(3).of(scrolling_element_top)\n  end\n\n  it 'can scroll an element to the bottom of the scrolling element' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    el = scrolling_element.find(:css, '#inner')\n    scrolling_element.scroll_to(el, align: :bottom)\n    el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')\n    scroller_bottom = scrolling_element.evaluate_script('this.getBoundingClientRect().top + this.clientHeight')\n    expect(el_bottom).to be_within(1).of(scroller_bottom)\n  end\n\n  it 'can scroll an element to the center of the scrolling element' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    el = scrolling_element.find(:css, '#inner')\n    scrolling_element.scroll_to(el, align: :center)\n    el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')\n    scrollable_center = scrolling_element.evaluate_script('(this.clientHeight / 2) + this.getBoundingClientRect().top')\n    # Firefox reports floats and can be slightly outside 1 difference - make 2 instaed\n    expect(el_center).to be_within(2).of(scrollable_center)\n  end\n\n  it 'can scroll the scrolling element to the top' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    scrolling_element.scroll_to :bottom\n    scrolling_element.scroll_to :top\n    expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, 0]\n  end\n\n  it 'can scroll the scrolling element to the bottom' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    scrolling_element.scroll_to :bottom\n    max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')\n    expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, max_scroll]\n  end\n\n  it 'can scroll the scrolling element to the vertical center' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    scrolling_element.scroll_to :center\n    max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')\n    expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to match [0, be_within(1).of(max_scroll / 2)]\n  end\n\n  it 'can scroll the scrolling element to specific location' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    scrolling_element.scroll_to 100, 100\n    expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [100, 100]\n  end\n\n  it 'can scroll the window by a specific amount' do\n    @session.scroll_to(:current, offset: [50, 75])\n    expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [50, 75]\n  end\n\n  it 'can scroll the scroll the scrolling element by a specific amount' do\n    scrolling_element = @session.find(:css, '#scrollable')\n    scrolling_element.scroll_to 100, 100\n    scrolling_element.scroll_to(:current, offset: [-50, 50])\n    expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [50, 150]\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/select_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#select' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should return value of the first option' do\n    expect(@session.find_field('Title').value).to eq('Mrs')\n  end\n\n  it 'should return value of the selected option' do\n    @session.select('Miss', from: 'Title')\n    expect(@session.find_field('Title').value).to eq('Miss')\n  end\n\n  it 'should allow selecting exact options where there are inexact matches', :exact_false do\n    @session.select('Mr', from: 'Title')\n    expect(@session.find_field('Title').value).to eq('Mr')\n  end\n\n  it 'should allow selecting options where they are the only inexact match', :exact_false do\n    @session.select('Mis', from: 'Title')\n    expect(@session.find_field('Title').value).to eq('Miss')\n  end\n\n  it 'should not allow selecting options where they are the only inexact match if `exact: true` is specified' do\n    sel = @session.find(:select, 'Title')\n    expect do\n      sel.select('Mis', exact: true)\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should not allow selecting an option if the match is ambiguous', :exact_false do\n    expect do\n      @session.select('M', from: 'Title')\n    end.to raise_error(Capybara::Ambiguous)\n  end\n\n  it 'should return the value attribute rather than content if present' do\n    expect(@session.find_field('Locale').value).to eq('en')\n  end\n\n  it 'should select an option from a select box by id' do\n    @session.select('Finnish', from: 'form_locale')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['locale']).to eq('fi')\n  end\n\n  it 'should select an option from a select box by label' do\n    @session.select('Finnish', from: 'Locale')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['locale']).to eq('fi')\n  end\n\n  it 'should select an option without giving a select box' do\n    @session.select('Swedish')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['locale']).to eq('sv')\n  end\n\n  it 'should escape quotes' do\n    @session.select(\"John's made-up language\", from: 'Locale')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['locale']).to eq('jo')\n  end\n\n  it 'should obey from' do\n    @session.select('Miss', from: 'Other title')\n    @session.click_button('awesome')\n    results = extract_results(@session)\n    expect(results['other_title']).to eq('Miss')\n    expect(results['title']).not_to eq('Miss')\n  end\n\n  it 'show match labels with preceding or trailing whitespace' do\n    @session.select('Lojban', from: 'Locale')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['locale']).to eq('jbo')\n  end\n\n  it 'casts to string' do\n    @session.select(:Miss, from: :Title)\n    expect(@session.find_field('Title').value).to eq('Miss')\n  end\n\n  context 'input with datalist' do\n    it 'should select an option' do\n      @session.select('Audi', from: 'manufacturer')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['manufacturer']).to eq('Audi')\n    end\n\n    it 'should not find an input without a datalist' do\n      expect do\n        @session.select('Thomas', from: 'form_first_name')\n      end.to raise_error(/Unable to find input box with datalist completion \"form_first_name\"/)\n    end\n\n    it \"should not select an option that doesn't exist\" do\n      expect do\n        @session.select('Tata', from: 'manufacturer')\n      end.to raise_error(/Unable to find datalist option \"Tata\"/)\n    end\n\n    it 'should not select a disabled option' do\n      expect do\n        @session.select('Mercedes', from: 'manufacturer')\n      end.to raise_error(/Unable to find datalist option \"Mercedes\"/)\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find select box \"does not exist\"/\n      expect do\n        @session.select('foo', from: 'does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context \"with an option that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /^Unable to find option \"Does not Exist\" within/\n      expect do\n        @session.select('Does not Exist', from: 'form_locale')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'on a disabled select' do\n    it 'should raise an error' do\n      expect do\n        @session.select('Should not see me', from: 'Disabled Select')\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'on a disabled option' do\n    it 'should not select' do\n      @session.select('Other', from: 'form_title')\n      expect(@session.find_field('form_title').value).not_to eq 'Other'\n    end\n  end\n\n  context 'with multiple select' do\n    it 'should return an empty value' do\n      expect(@session.find_field('Languages').value).to eq([])\n    end\n\n    it 'should return value of the selected options' do\n      @session.select('Ruby',       from: 'Languages')\n      @session.select('Javascript', from: 'Languages')\n      expect(@session.find_field('Languages').value).to include('Ruby', 'Javascript')\n    end\n\n    it 'should select one option' do\n      @session.select('Ruby', from: 'Languages')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['languages']).to eq(['Ruby'])\n    end\n\n    it 'should select multiple options' do\n      @session.select('Ruby',       from: 'Languages')\n      @session.select('Javascript', from: 'Languages')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['languages']).to include('Ruby', 'Javascript')\n    end\n\n    it 'should remain selected if already selected' do\n      @session.select('Ruby',       from: 'Languages')\n      @session.select('Javascript', from: 'Languages')\n      @session.select('Ruby',       from: 'Languages')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['languages']).to include('Ruby', 'Javascript')\n    end\n\n    it 'should return value attribute rather than content if present' do\n      expect(@session.find_field('Underwear').value).to include('thermal')\n    end\n  end\n\n  context 'with :exact option' do\n    context 'when `false`' do\n      it 'can match select box approximately' do\n        @session.select('Finnish', from: 'Loc', exact: false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['locale']).to eq('fi')\n      end\n\n      it 'can match option approximately' do\n        @session.select('Fin', from: 'Locale', exact:  false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['locale']).to eq('fi')\n      end\n\n      it 'can match option approximately when :from not given' do\n        @session.select('made-up language', exact:  false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['locale']).to eq('jo')\n      end\n    end\n\n    context 'when `true`' do\n      it 'can match select box approximately' do\n        expect do\n          @session.select('Finnish', from: 'Loc', exact: true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n\n      it 'can match option approximately' do\n        expect do\n          @session.select('Fin', from: 'Locale', exact: true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n\n      it 'can match option approximately when :from not given' do\n        expect do\n          @session.select('made-up language', exact: true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n  end\n\n  it 'should error when not passed a locator for :from option' do\n    select = @session.find(:select, 'Title')\n    expect { @session.select('Mr', from: select) }.to raise_error(ArgumentError, /does not take an element/)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/selectors_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec Capybara::Selector do\n  before do\n    @session.visit('/form')\n  end\n\n  describe ':label selector' do\n    it 'finds a label by text' do\n      expect(@session.find(:label, 'Customer Name').text).to eq 'Customer Name'\n    end\n\n    it 'finds a label by for attribute string' do\n      expect(@session.find(:label, for: 'form_other_title')['for']).to eq 'form_other_title'\n    end\n\n    it 'finds a label for for attribute regex' do\n      expect(@session.find(:label, for: /_other_title/)['for']).to eq 'form_other_title'\n    end\n\n    it 'finds a label from nested input using :for filter with id string' do\n      expect(@session.find(:label, for: 'nested_label').text).to eq 'Nested Label'\n    end\n\n    it 'finds a label from nested input using :for filter with id regexp' do\n      expect(@session.find(:label, for: /nested_lab/).text).to eq 'Nested Label'\n    end\n\n    it 'finds a label from nested input using :for filter with element' do\n      input = @session.find(:id, 'nested_label')\n      expect(@session.find(:label, for: input).text).to eq 'Nested Label'\n    end\n\n    it 'finds a label from nested input using :for filter with element when no id on label' do\n      input = @session.find(:css, '#wrapper_label').find(:css, 'input')\n      expect(@session.find(:label, for: input).text).to eq 'Wrapper Label'\n    end\n\n    it 'finds the label for an non-nested element when using :for filter' do\n      select = @session.find(:id, 'form_other_title')\n      expect(@session.find(:label, for: select)['for']).to eq 'form_other_title'\n    end\n\n    context 'with exact option' do\n      it 'matches substrings' do\n        expect(@session.find(:label, 'Customer Na', exact: false).text).to eq 'Customer Name'\n      end\n\n      it \"doesn't match substrings\" do\n        expect { @session.find(:label, 'Customer Na', exact: true) }.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n  end\n\n  describe 'field selectors' do\n    context 'with :id option' do\n      it 'can find specifically by id' do\n        expect(@session.find(:field, id: 'customer_email').value).to eq 'ben@ben.com'\n      end\n\n      it 'can find by regex' do\n        expect(@session.find(:field, id: /ustomer.emai/).value).to eq 'ben@ben.com'\n      end\n\n      it 'can find by case-insensitive id' do\n        expect(@session.find(:field, id: /StOmer.emAI/i).value).to eq 'ben@ben.com'\n      end\n    end\n\n    it 'can find specifically by name string' do\n      expect(@session.find(:field, name: 'form[other_title]')['id']).to eq 'form_other_title'\n    end\n\n    it 'can find specifically by name regex' do\n      expect(@session.find(:field, name: /form\\[other_.*\\]/)['id']).to eq 'form_other_title'\n    end\n\n    it 'can find specifically by placeholder string' do\n      expect(@session.find(:field, placeholder: 'FirstName')['id']).to eq 'form_first_name'\n    end\n\n    it 'can find specifically by placeholder regex' do\n      expect(@session.find(:field, placeholder: /FirstN.*/)['id']).to eq 'form_first_name'\n    end\n\n    it 'can find by type' do\n      expect(@session.find(:field, 'Confusion', type: 'checkbox')['id']).to eq 'confusion_checkbox'\n      expect(@session.find(:field, 'Confusion', type: 'text')['id']).to eq 'confusion_text'\n      expect(@session.find(:field, 'Confusion', type: 'textarea')['id']).to eq 'confusion_textarea'\n    end\n\n    it 'can find by class' do\n      expect(@session.find(:field, class: 'confusion-checkbox')['id']).to eq 'confusion_checkbox'\n      expect(@session).to have_selector(:field, class: 'confusion', count: 3)\n      expect(@session.find(:field, class: %w[confusion confusion-textarea])['id']).to eq 'confusion_textarea'\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/sibling_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#sibling' do\n  before do\n    @session.visit('/with_html')\n  end\n\n  after do\n    Capybara::Selector.remove(:monkey)\n  end\n\n  it 'should find a prior sibling element using the given locator' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el.sibling('//div[@data-pre]')[:id]).to eq('pre_sibling')\n  end\n\n  it 'should find a following sibling element using the given locator' do\n    el = @session.find(:css, '#mid_sibling')\n    expect(el.sibling('//div[@data-post]')[:id]).to eq('post_sibling')\n  end\n\n  it 'should raise an error if there are multiple matches' do\n    el = @session.find(:css, '#mid_sibling')\n    expect { el.sibling('//div') }.to raise_error(Capybara::Ambiguous)\n  end\n\n  context 'with css selectors' do\n    it 'should find the first element using the given locator' do\n      el = @session.find(:css, '#mid_sibling')\n      expect(el.sibling(:css, '#pre_sibling')).to have_text('Pre Sibling')\n      expect(el.sibling(:css, '#post_sibling')).to have_text('Post Sibling')\n    end\n  end\n\n  context 'with custom selector' do\n    it 'should use the custom selector' do\n      Capybara.add_selector(:data_attribute) do\n        xpath { |attr| \".//*[@data-#{attr}]\" }\n      end\n      el = @session.find(:css, '#mid_sibling')\n      expect(el.sibling(:data_attribute, 'pre').text).to eq('Pre Sibling')\n      expect(el.sibling(:data_attribute, 'post').text).to eq('Post Sibling')\n    end\n  end\n\n  it 'should raise ElementNotFound with a useful default message if nothing was found' do\n    el = @session.find(:css, '#child')\n    expect do\n      el.sibling(:xpath, '//div[@id=\"nosuchthing\"]')\n    end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath \"//div[@id=\\\\\"nosuchthing\\\\\"]\" that is a sibling of visible css \"#child\"')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/text_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#text' do\n  it 'should print the text of the page' do\n    @session.visit('/with_simple_html')\n    expect(@session.text).to eq('Bar')\n  end\n\n  it 'ignores invisible text by default' do\n    @session.visit('/with_html')\n    expect(@session.find(:id, 'hidden-text').text).to eq('Some of this text is')\n  end\n\n  it 'shows invisible text if `:all` given' do\n    @session.visit('/with_html')\n    expect(@session.find(:id, 'hidden-text').text(:all)).to eq('Some of this text is hidden!')\n  end\n\n  it 'ignores invisible text if `:visible` given' do\n    Capybara.ignore_hidden_elements = false\n    @session.visit('/with_html')\n    expect(@session.find(:id, 'hidden-text').text(:visible)).to eq('Some of this text is')\n  end\n\n  it 'ignores invisible text if `Capybara.ignore_hidden_elements = true`' do\n    @session.visit('/with_html')\n    expect(@session.find(:id, 'hidden-text').text).to eq('Some of this text is')\n    Capybara.ignore_hidden_elements = false\n    expect(@session.find(:id, 'hidden-text').text).to eq('Some of this text is hidden!')\n  end\n\n  it 'ignores invisible text if `Capybara.visible_text_only = true`' do\n    @session.visit('/with_html')\n    Capybara.visible_text_only = true\n    expect(@session.find(:id, 'hidden-text').text).to eq('Some of this text is')\n    Capybara.ignore_hidden_elements = false\n    expect(@session.find(:id, 'hidden-text').text).to eq('Some of this text is')\n  end\n\n  it 'ignores invisible text if ancestor is invisible' do\n    @session.visit('/with_html')\n    expect(@session.find(:id, 'hidden_via_ancestor', visible: false).text).to eq('')\n  end\n\n  context 'with css as default selector' do\n    before { Capybara.default_selector = :css }\n\n    after { Capybara.default_selector = :xpath }\n\n    it 'should print the text of the page' do\n      @session.visit('/with_simple_html')\n      expect(@session.text).to eq('Bar')\n    end\n  end\n\n  it 'should be correctly normalized when visible' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#normalized')\n    expect(el.text).to eq \"Some text\\nMore text\\nAnd more text\\nEven more    text on multiple lines\"\n  end\n\n  it 'should be a textContent with irrelevant whitespace collapsed when non-visible' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#non_visible_normalized', visible: false)\n    expect(el.text(:all)).to eq 'Some textMore text And more text Even more    text on multiple lines'\n  end\n\n  it 'should strip correctly' do\n    @session.visit('/with_html')\n    el = @session.find(:css, '#ws')\n    expect(el.text).to eq ' '\n    expect(el.text(:all)).to eq ' '\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/title_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#title' do\n  it 'should get the title of the page' do\n    @session.visit('/with_title')\n    expect(@session.title).to eq('Test Title')\n  end\n\n  context 'with css as default selector' do\n    before { Capybara.default_selector = :css }\n\n    after { Capybara.default_selector = :xpath }\n\n    it 'should get the title of the page' do\n      @session.visit('/with_title')\n      expect(@session.title).to eq('Test Title')\n    end\n  end\n\n  context 'within iframe', requires: [:frames] do\n    it 'should get the title of the top level browsing context' do\n      @session.visit('/within_frames')\n      expect(@session.title).to eq('With Frames')\n      @session.within_frame('frameOne') do\n        expect(@session.title).to eq('With Frames')\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/uncheck_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#uncheck' do\n  before do\n    @session.visit('/form')\n  end\n\n  it 'should uncheck a checkbox by id' do\n    @session.uncheck('form_pets_hamster')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog')\n    expect(extract_results(@session)['pets']).not_to include('hamster')\n  end\n\n  it 'should uncheck a checkbox by label' do\n    @session.uncheck('Hamster')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog')\n    expect(extract_results(@session)['pets']).not_to include('hamster')\n  end\n\n  it 'should work without a locator string' do\n    @session.uncheck(id: 'form_pets_hamster')\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog')\n    expect(extract_results(@session)['pets']).not_to include('hamster')\n  end\n\n  it 'should be able to uncheck itself if no locator specified' do\n    cb = @session.find(:id, 'form_pets_hamster')\n    cb.uncheck\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog')\n    expect(extract_results(@session)['pets']).not_to include('hamster')\n  end\n\n  it 'casts to string' do\n    @session.uncheck(:form_pets_hamster)\n    @session.click_button('awesome')\n    expect(extract_results(@session)['pets']).to include('dog')\n    expect(extract_results(@session)['pets']).not_to include('hamster')\n  end\n\n  context 'with :exact option' do\n    it 'should accept partial matches when false' do\n      @session.uncheck('Ham', exact:  false)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['pets']).not_to include('hamster')\n    end\n\n    it 'should not accept partial matches when true' do\n      expect do\n        @session.uncheck('Ham', exact: true)\n      end.to raise_error(Capybara::ElementNotFound)\n    end\n  end\n\n  context 'when checkbox hidden' do\n    context 'with Capybara.automatic_label_click == true' do\n      around do |spec|\n        old_click_label, Capybara.automatic_label_click = Capybara.automatic_label_click, true\n        spec.run\n        Capybara.automatic_label_click = old_click_label\n      end\n\n      it 'should uncheck via clicking the label with :for attribute if possible' do\n        expect(@session.find(:checkbox, 'form_cars_jaguar', checked: true, visible: :hidden)).to be_truthy\n        @session.uncheck('form_cars_jaguar')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).not_to include('jaguar')\n      end\n\n      it 'should uncheck via clicking the wrapping label if possible' do\n        expect(@session.find(:checkbox, 'form_cars_koenigsegg', checked: true, visible: :hidden)).to be_truthy\n        @session.uncheck('form_cars_koenigsegg')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).not_to include('koenigsegg')\n      end\n\n      it 'should not click the label if unneeded' do\n        expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy\n        @session.uncheck('form_cars_tesla')\n        @session.click_button('awesome')\n        expect(extract_results(@session)['cars']).not_to include('tesla')\n      end\n\n      it 'should raise original error when no label available' do\n        expect { @session.uncheck('form_cars_porsche') }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox \"form_cars_porsche\"/)\n      end\n\n      it 'should raise error if not allowed to click label' do\n        expect { @session.uncheck('form_cars_jaguar', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox \"form_cars_jaguar\"/)\n      end\n\n      it 'should include node filter description in error if necessary' do\n        expect { @session.uncheck('form_cars_maserati', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, 'Unable to find visible checkbox \"form_cars_maserati\" that is not disabled')\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/unselect_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#unselect' do\n  before do\n    @session.visit('/form')\n  end\n\n  context 'with multiple select' do\n    it 'should unselect an option from a select box by id' do\n      @session.unselect('Commando', from: 'form_underwear')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).to include('Briefs', 'Boxerbriefs')\n      expect(extract_results(@session)['underwear']).not_to include('Commando')\n    end\n\n    it 'should unselect an option without a select box' do\n      @session.unselect('Commando')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).to include('Briefs', 'Boxerbriefs')\n      expect(extract_results(@session)['underwear']).not_to include('Commando')\n    end\n\n    it 'should unselect an option from a select box by label' do\n      @session.unselect('Commando', from: 'Underwear')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).to include('Briefs', 'Boxerbriefs')\n      expect(extract_results(@session)['underwear']).not_to include('Commando')\n    end\n\n    it 'should favour exact matches to option labels' do\n      @session.unselect('Briefs', from: 'Underwear')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).to include('Commando', 'Boxerbriefs')\n      expect(extract_results(@session)['underwear']).not_to include('Briefs')\n    end\n\n    it 'should escape quotes' do\n      @session.unselect(\"Frenchman's Pantalons\", from: 'Underwear')\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).not_to include(\"Frenchman's Pantalons\")\n    end\n\n    it 'casts to string' do\n      @session.unselect(:Briefs, from: :Underwear)\n      @session.click_button('awesome')\n      expect(extract_results(@session)['underwear']).to include('Commando', 'Boxerbriefs')\n      expect(extract_results(@session)['underwear']).not_to include('Briefs')\n    end\n  end\n\n  context 'with single select' do\n    it 'should raise an error' do\n      expect { @session.unselect('English', from: 'form_locale') }.to raise_error(Capybara::UnselectNotAllowed)\n    end\n  end\n\n  context \"with a locator that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /Unable to find select box \"does not exist\"/\n      expect do\n        @session.unselect('foo', from: 'does not exist')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context \"with an option that doesn't exist\" do\n    it 'should raise an error' do\n      msg = /^Unable to find option \"Does not Exist\" within/\n      expect do\n        @session.unselect('Does not Exist', from: 'form_underwear')\n      end.to raise_error(Capybara::ElementNotFound, msg)\n    end\n  end\n\n  context 'with :exact option' do\n    context 'when `false`' do\n      it 'can match select box approximately' do\n        @session.unselect('Boxerbriefs', from: 'Under', exact: false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['underwear']).not_to include('Boxerbriefs')\n      end\n\n      it 'can match option approximately' do\n        @session.unselect('Boxerbr', from: 'Underwear', exact: false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['underwear']).not_to include('Boxerbriefs')\n      end\n\n      it 'can match option approximately when :from not given' do\n        @session.unselect('Boxerbr', exact: false)\n        @session.click_button('awesome')\n        expect(extract_results(@session)['underwear']).not_to include('Boxerbriefs')\n      end\n    end\n\n    context 'when `true`' do\n      it 'can match select box approximately' do\n        expect do\n          @session.unselect('Boxerbriefs', from: 'Under', exact:  true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n\n      it 'can match option approximately' do\n        expect do\n          @session.unselect('Boxerbr', from: 'Underwear', exact:  true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n\n      it 'can match option approximately when :from not given' do\n        expect do\n          @session.unselect('Boxerbr', exact: true)\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/visit_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#visit' do\n  it 'should fetch a response from the driver with a relative url' do\n    @session.visit('/')\n    expect(@session).to have_content('Hello world!')\n    @session.visit('/foo')\n    expect(@session).to have_content('Another World')\n  end\n\n  it 'should fetch a response from the driver with an absolute url with a port' do\n    # Preparation\n    @session.visit('/')\n    root_uri = URI.parse(@session.current_url)\n\n    @session.visit(\"http://#{root_uri.host}:#{root_uri.port}/\")\n    expect(@session).to have_content('Hello world!')\n    @session.visit(\"http://#{root_uri.host}:#{root_uri.port}/foo\")\n    expect(@session).to have_content('Another World')\n  end\n\n  it \"should fetch a response when absolute URI doesn't have a trailing slash\" do\n    # Preparation\n    @session.visit('/foo/bar')\n    root_uri = URI.parse(@session.current_url)\n\n    @session.visit(\"http://#{root_uri.host}:#{root_uri.port}\")\n    expect(@session).to have_content('Hello world!')\n  end\n\n  it 'should fetch a response when sequentially visiting same destination with a target' do\n    @session.visit('/form')\n    expect(@session).to have_css('#form_title')\n    @session.visit('/form#form_title')\n    expect(@session).to have_css('#form_title')\n  end\n\n  it 'raises any errors caught inside the server', requires: [:server] do\n    quietly { @session.visit('/error') }\n    expect do\n      @session.visit('/')\n    end.to raise_error(TestApp::TestAppError)\n  end\n\n  it 'should be able to open non-http url', requires: [:about_scheme] do\n    @session.visit('about:blank')\n    @session.assert_no_selector :xpath, '/html/body/*'\n  end\n\n  context 'when Capybara.always_include_port is true' do\n    let(:root_uri) do\n      @session.visit('/')\n      URI.parse(@session.current_url)\n    end\n\n    before do\n      Capybara.always_include_port = true\n    end\n\n    after do\n      Capybara.always_include_port = false\n    end\n\n    it 'should fetch a response from the driver with an absolute url without a port' do\n      @session.visit(\"http://#{root_uri.host}/\")\n      expect(URI.parse(@session.current_url).port).to eq(root_uri.port)\n      expect(@session).to have_content('Hello world!')\n\n      @session.visit(\"http://#{root_uri.host}/foo\")\n      expect(URI.parse(@session.current_url).port).to eq(root_uri.port)\n      expect(@session).to have_content('Another World')\n    end\n\n    it 'should add the server port to a visited url if no port specified', requires: [:server] do\n      allow(@session.driver).to receive(:visit)\n      @session.visit('http://www.example.com')\n      expect(@session.driver).to have_received(:visit).with(\"http://www.example.com:#{@session.server.port}\")\n    end\n\n    it 'should not override the visit specified port even if default for scheme', requires: [:server] do\n      allow(@session.driver).to receive(:visit)\n      @session.visit('http://www.example.com:80')\n      expect(@session.driver).to have_received(:visit).with('http://www.example.com:80')\n    end\n\n    it 'should give preference to app_host port if specified', requires: [:server] do\n      allow(@session.driver).to receive(:visit)\n      Capybara.app_host = 'http://www.example.com:6666'\n      @session.visit('/random')\n      expect(@session.driver).to have_received(:visit).with('http://www.example.com:6666/random')\n    end\n\n    it \"shouldn't override port if no server\", requires: [:server] do\n      session = Capybara::Session.new(@session.mode, nil)\n      allow(session.driver).to receive(:visit)\n      session.visit('http://www.google.com')\n      expect(session.driver).to have_received(:visit).with('http://www.google.com')\n    end\n\n    it \"shouldn't override port if no server but app_host is set\", requires: [:server] do\n      session = Capybara::Session.new(@session.mode, nil)\n      Capybara.app_host = 'http://www.example.com:6666'\n      allow(session.driver).to receive(:visit)\n      session.visit('http://www.google.com')\n      expect(session.driver).to have_received(:visit).with('http://www.google.com')\n    end\n  end\n\n  context 'when Capybara.always_include_port is false' do\n    before do\n      Capybara.always_include_port = false\n    end\n\n    it \"shouldn't overwrite port if app_host is set\", requires: [:server] do\n      session = Capybara::Session.new(@session.mode, nil)\n      Capybara.app_host = 'http://www.example.com:6666'\n      allow(session.driver).to receive(:visit)\n      session.visit('http://www.google.com')\n      expect(session.driver).to have_received(:visit).with('http://www.google.com')\n    end\n\n    it \"shouldn't overwrite port if port specfified\", requires: [:server] do\n      session = Capybara::Session.new(@session.mode, nil)\n      Capybara.app_host = 'http://www.example.com:6666'\n      allow(session.driver).to receive(:visit)\n      session.visit('http://www.google.com:99')\n      expect(session.driver).to have_received(:visit).with('http://www.google.com:99')\n    end\n  end\n\n  context 'without a server', requires: [:server] do\n    it 'should respect `app_host`' do\n      serverless_session = Capybara::Session.new(@session.mode, nil)\n      Capybara.app_host = \"http://#{@session.server.host}:#{@session.server.port}\"\n      serverless_session.visit('/foo')\n      expect(serverless_session).to have_content('Another World')\n    end\n\n    it 'should visit a fully qualified URL' do\n      serverless_session = Capybara::Session.new(@session.mode, nil)\n      serverless_session.visit(\"http://#{@session.server.host}:#{@session.server.port}/foo\")\n      expect(serverless_session).to have_content('Another World')\n    end\n  end\n\n  context 'with Capybara.app_host set' do\n    it 'should override server', requires: [:server] do\n      another_session = Capybara::Session.new(@session.mode, @session.app.dup)\n      Capybara.app_host = \"http://#{@session.server.host}:#{@session.server.port}\"\n      another_session.visit('/foo')\n      expect(another_session).to have_content('Another World')\n      expect(another_session.current_url).to start_with(Capybara.app_host)\n      expect(URI.parse(another_session.current_url).port).not_to eq another_session.server.port\n      expect(URI.parse(another_session.current_url).port).to eq @session.server.port\n    end\n\n    it 'should append relative path', requires: [:server] do\n      Capybara.app_host = \"http://#{@session.server.host}:#{@session.server.port}/redirect/0\"\n      @session.visit('/times')\n      expect(@session).to have_content('redirection complete')\n    end\n\n    it 'should work if `app_host` has a trailing /', requires: [:server] do\n      Capybara.app_host = \"http://#{@session.server.host}:#{@session.server.port}/\"\n      @session.visit('/')\n      expect(@session).to have_content('Hello world!')\n    end\n  end\n\n  it 'should send no referer when visiting a page' do\n    @session.visit '/get_referer'\n    expect(@session).to have_content 'No referer'\n  end\n\n  it 'should send no referer when visiting a second page' do\n    @session.visit '/get_referer'\n    @session.visit '/get_referer'\n    expect(@session).to have_content 'No referer'\n  end\n\n  it 'should send a referer when following a link' do\n    @session.visit '/referer_base'\n    @session.find('//a[@href=\"/get_referer\"]').click\n    expect(@session).to have_content %r{http://.*/referer_base}\n  end\n\n  it 'should preserve the original referer URL when following a redirect' do\n    @session.visit('/referer_base')\n    @session.find('//a[@href=\"/redirect_to_get_referer\"]').click\n    expect(@session).to have_content %r{http://.*/referer_base}\n  end\n\n  it 'should send a referer when submitting a form' do\n    @session.visit '/referer_base'\n    @session.find('//input').click\n    expect(@session).to have_content %r{http://.*/referer_base}\n  end\n\n  it 'can set cookie if a blank path is specified' do\n    @session.visit('')\n    @session.visit('/get_cookie')\n    expect(@session).to have_content('root cookie')\n  end\n\n  context 'with base element' do\n    it 'should use base href with relative links' do\n      @session.visit('/base/with_base')\n      @session.click_link('Title page')\n      expect(@session).to have_current_path('/with_title')\n    end\n\n    it 'should use base href with bare queries' do\n      @session.visit('/base/with_base')\n      @session.click_link('Bare query')\n      expect(@session).to have_current_path('/?a=3')\n    end\n\n    it 'should not use the base href with a new visit call' do\n      @session.visit('/base/with_other_base')\n      @session.visit('with_html')\n      expect(@session).to have_current_path('/with_html')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/become_closed_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#become_closed', requires: %i[windows js] do\n  let!(:window) { @session.current_window }\n  let(:other_window) do\n    @session.window_opened_by do\n      @session.find(:css, '#openWindow').click\n    end\n  end\n\n  before do\n    @session.visit('/with_windows')\n  end\n\n  after do\n    @session.document.synchronize(5, errors: [Capybara::CapybaraError]) do\n      raise Capybara::CapybaraError if @session.windows.size != 1\n    end\n    @session.switch_to_window(window)\n  end\n\n  context 'with :wait option' do\n    it 'should wait if value of :wait is more than timeout' do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 500);')\n      end\n      Capybara.using_wait_time 0.1 do\n        expect(other_window).to become_closed(wait: 5)\n      end\n    end\n\n    it 'should raise error if value of :wait is less than timeout' do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 1000);')\n      end\n      Capybara.using_wait_time 2 do\n        expect do\n          expect(other_window).to become_closed(wait: 0.2)\n        end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\\Aexpected #<Window @handle=\".+\"> to become closed after 0.2 seconds\\Z/)\n      end\n    end\n  end\n\n  context 'without :wait option' do\n    it 'should wait if value of default_max_wait_time is more than timeout' do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 500);')\n      end\n      Capybara.using_wait_time 5 do\n        expect(other_window).to become_closed\n      end\n    end\n\n    it 'should raise error if value of default_max_wait_time is less than timeout' do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 900);')\n      end\n      Capybara.using_wait_time 0.4 do\n        expect do\n          expect(other_window).to become_closed\n        end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\\Aexpected #<Window @handle=\".+\"> to become closed after 0.4 seconds\\Z/)\n      end\n    end\n  end\n\n  context 'with not_to' do\n    it \"should not raise error if window doesn't close before default_max_wait_time\" do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 1000);')\n      end\n      Capybara.using_wait_time 0.3 do\n        expect do\n          expect(other_window).not_to become_closed\n        end.not_to raise_error\n      end\n    end\n\n    it 'should raise error if window closes before default_max_wait_time' do\n      @session.within_window other_window do\n        @session.execute_script('setTimeout(function(){ window.close(); }, 700);')\n      end\n      Capybara.using_wait_time 3.1 do\n        expect do\n          expect(other_window).not_to become_closed\n        end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\\Aexpected #<Window @handle=\".+\"> not to become closed after 3.1 seconds\\Z/)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/current_window_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#current_window', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n  end\n\n  after do\n    (@session.windows - [@window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(@window)\n  end\n\n  it 'should return window' do\n    expect(@session.current_window).to be_instance_of(Capybara::Window)\n  end\n\n  it 'should be modified by switching to another window' do\n    window = @session.window_opened_by { @session.find(:css, '#openWindow').click }\n\n    expect do\n      @session.switch_to_window(window)\n    end.to change { @session.current_window }.from(@window).to(window)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/open_new_window_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#open_new_window', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n  end\n\n  after do\n    (@session.windows - [@window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(@window)\n  end\n\n  it 'should open new window with blank url and title' do\n    window = @session.open_new_window\n    @session.switch_to_window(window)\n    expect(@session.title).to satisfy('be a blank title') { |title| ['', 'about:blank'].include? title }\n    expect(@session.current_url).to eq('about:blank')\n  end\n\n  it 'should open window with changeable content' do\n    window = @session.open_new_window\n    @session.within_window window do\n      @session.visit '/with_html'\n      expect(@session).to have_css('#first')\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/switch_to_window_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec '#switch_to_window', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n    @session.assert_selector(:css, 'body.loaded')\n  end\n\n  after do\n    (@session.windows - [@window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(@window)\n  end\n\n  it 'should raise error when invoked without args' do\n    expect do\n      @session.switch_to_window\n    end.to raise_error(ArgumentError, '`switch_to_window`: either window or block should be provided')\n  end\n\n  it 'should raise error when invoked with window and block' do\n    expect do\n      @session.switch_to_window(@window) { @session.title == 'Title of the first popup' }\n    end.to raise_error(ArgumentError, '`switch_to_window` can take either a block or a window, not both')\n  end\n\n  context 'with an instance of Capybara::Window' do\n    it 'should be able to switch to window' do\n      window = @session.open_new_window\n      expect(@session.title).to eq('With Windows')\n      @session.switch_to_window(window)\n      expect(@session.title).to satisfy('be a blank title') { |title| ['', 'about:blank'].include? title }\n    end\n\n    it 'should raise error when closed window is passed' do\n      original_window = @session.current_window\n      new_window = @session.open_new_window\n      @session.switch_to_window(new_window)\n      new_window.close\n      @session.switch_to_window(original_window)\n      expect do\n        @session.switch_to_window(new_window)\n      end.to raise_error(@session.driver.no_such_window_error)\n    end\n  end\n\n  context 'with block' do\n    before do\n      @session.find(:css, '#openTwoWindows').click\n      sleep(1) # wait for the windows to open\n    end\n\n    it 'should be able to switch to current window' do\n      @session.switch_to_window { @session.title == 'With Windows' }\n      expect(@session).to have_css('#openTwoWindows')\n    end\n\n    it 'should find the div in another window' do\n      @session.switch_to_window { @session.title == 'Title of popup two' }\n      expect(@session).to have_css('#divInPopupTwo')\n    end\n\n    it 'should be able to switch multiple times' do\n      @session.switch_to_window { @session.title == 'Title of the first popup' }\n      expect(@session).to have_css('#divInPopupOne')\n      @session.switch_to_window { @session.title == 'Title of popup two' }\n      expect(@session).to have_css('#divInPopupTwo')\n    end\n\n    it 'should return window' do\n      window = @session.switch_to_window { @session.title == 'Title of popup two' }\n      expect(@session.windows - [@window]).to include(window)\n    end\n\n    it \"should raise error when invoked inside `within` as it's nonsense\" do\n      expect do\n        @session.within(:css, '#doesNotOpenWindows') do\n          @session.switch_to_window { @session.title == 'With Windows' }\n        end\n      end.to raise_error(Capybara::ScopeError, /`switch_to_window` is not supposed to be invoked/)\n    end\n\n    it \"should raise error when invoked inside `within_frame` as it's nonsense\" do\n      expect do\n        @session.within_frame('frameOne') do\n          @session.switch_to_window { @session.title == 'With Windows' }\n        end\n      end.to raise_error(Capybara::ScopeError, /`switch_to_window` is not supposed to be invoked from/)\n    end\n\n    it 'should allow to be called inside within_window and within_window will still return to original' do\n      other_windows = (@session.windows - [@window])\n      expect(@session.current_window).to eq(@window)\n      @session.within_window other_windows[0] do\n        expect(@session.current_window).to eq(other_windows[0])\n        @session.switch_to_window other_windows[1]\n        expect(@session.current_window).to eq(other_windows[1])\n      end\n      expect(@session.current_window).to eq(@window)\n    end\n\n    it \"should raise error if window matching block wasn't found\" do\n      original = @session.current_window\n      expect do\n        @session.switch_to_window { @session.title == 'A title' }\n      end.to raise_error(Capybara::WindowError, 'Could not find a window matching block/lambda')\n      expect(@session.current_window).to eq(original)\n    end\n\n    it 'should switch to original window if error is raised inside block' do\n      original = @session.switch_to_window(@session.windows[1])\n      expect do\n        @session.switch_to_window { raise 'error' }\n      end.to raise_error(StandardError, 'error')\n      expect(@session.current_window).to eq(original)\n    end\n  end\n\n  it 'should wait for window to appear' do\n    @session.find(:css, '#openWindowWithTimeout').click\n    expect do\n      @session.switch_to_window(wait: 5) { @session.title == 'Title of the first popup' }\n    end.not_to raise_error\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/window_opened_by_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec '#window_opened_by', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n    @session.assert_selector(:css, 'body.loaded')\n  end\n\n  after do\n    (@session.windows - [@window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(@window)\n  end\n\n  let(:zero_windows_message) { 'block passed to #window_opened_by opened 0 windows instead of 1' }\n  let(:two_windows_message) { 'block passed to #window_opened_by opened 2 windows instead of 1' }\n\n  context 'with :wait option' do\n    it 'should raise error if value of :wait is less than timeout' do\n      # So large value is used as `driver.window_handles` takes up to 800 ms on Travis\n      Capybara.using_wait_time 2 do\n        button = @session.find(:css, '#openWindowWithLongerTimeout')\n        expect do\n          @session.window_opened_by(wait: 0.3) do\n            button.click\n          end\n        end.to raise_error(Capybara::WindowError, zero_windows_message)\n      end\n      @session.document.synchronize(5, errors: [Capybara::CapybaraError]) do\n        raise Capybara::CapybaraError if @session.windows.size != 2\n      end\n    end\n\n    it 'should find window if value of :wait is more than timeout' do\n      button = @session.find(:css, '#openWindowWithTimeout')\n      Capybara.using_wait_time 0.1 do\n        window = @session.window_opened_by(wait: 1.5) do\n          button.click\n        end\n        expect(window).to be_instance_of(Capybara::Window)\n      end\n    end\n  end\n\n  context 'without :wait option' do\n    it 'should raise error if default_max_wait_time is less than timeout' do\n      button = @session.find(:css, '#openWindowWithTimeout')\n      Capybara.using_wait_time 0.1 do\n        expect do\n          @session.window_opened_by do\n            button.click\n          end\n        end.to raise_error(Capybara::WindowError, zero_windows_message)\n      end\n      @session.document.synchronize(2, errors: [Capybara::CapybaraError]) do\n        raise Capybara::CapybaraError if @session.windows.size != 2\n      end\n    end\n\n    it 'should find window if default_max_wait_time is more than timeout' do\n      button = @session.find(:css, '#openWindowWithTimeout')\n      Capybara.using_wait_time 5 do\n        window = @session.window_opened_by do\n          button.click\n        end\n        expect(window).to be_instance_of(Capybara::Window)\n      end\n    end\n  end\n\n  it 'should raise error when two windows have been opened by block' do\n    button = @session.find(:css, '#openTwoWindows')\n    expect do\n      @session.window_opened_by do\n        button.click\n        sleep 1 # It's possible for window_opened_by to be fullfilled before the second window opens\n      end\n    end.to raise_error(Capybara::WindowError, two_windows_message)\n    @session.document.synchronize(2, errors: [Capybara::CapybaraError]) do\n      raise Capybara::CapybaraError if @session.windows.size != 3\n    end\n  end\n\n  it 'should raise error when no windows were opened by block' do\n    button = @session.find(:css, '#doesNotOpenWindows')\n    expect do\n      @session.window_opened_by do\n        button.click\n      end\n    end.to raise_error(Capybara::WindowError, zero_windows_message)\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/window_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec Capybara::Window, requires: [:windows] do\n  let!(:orig_window) { @session.current_window }\n  before do\n    @session.visit('/with_windows')\n  end\n\n  after do\n    (@session.windows - [orig_window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(orig_window)\n  end\n\n  describe '#exists?' do\n    it 'should become false after window was closed' do\n      other_window = @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n\n      expect do\n        @session.switch_to_window other_window\n        other_window.close\n      end.to change(other_window, :exists?).from(true).to(false)\n    end\n  end\n\n  describe '#closed?' do\n    it 'should become true after window was closed' do\n      other_window = @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n      expect do\n        @session.switch_to_window other_window\n        other_window.close\n      end.to change { other_window.closed? }.from(false).to(true)\n    end\n  end\n\n  describe '#current?' do\n    let(:other_window) do\n      @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n    end\n\n    it 'should become true after switching to window' do\n      expect do\n        @session.switch_to_window(other_window)\n      end.to change(other_window, :current?).from(false).to(true)\n    end\n\n    it 'should return false if window is closed' do\n      @session.switch_to_window(other_window)\n      other_window.close\n      expect(other_window.current?).to be(false)\n    end\n  end\n\n  describe '#close' do\n    let!(:other_window) do\n      @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n    end\n\n    it 'should switch to original window if invoked not for current window' do\n      expect(@session.windows.size).to eq(2)\n      expect(@session.current_window).to eq(orig_window)\n      other_window.close\n      expect(@session.windows.size).to eq(1)\n      expect(@session.current_window).to eq(orig_window)\n    end\n\n    it 'should make subsequent invocations of other methods raise no_such_window_error if invoked for current window' do\n      @session.switch_to_window(other_window)\n      expect(@session.current_window).to eq(other_window)\n      other_window.close\n      expect do\n        @session.find(:css, '#some_id')\n      end.to raise_error(@session.driver.no_such_window_error)\n      @session.switch_to_window(orig_window)\n    end\n  end\n\n  describe '#size' do\n    def win_size\n      @session.evaluate_script('[window.outerWidth || window.innerWidth, window.outerHeight || window.innerHeight]')\n    end\n\n    it 'should return size of whole window', requires: %i[windows js] do\n      expect(@session.current_window.size).to eq win_size\n    end\n\n    it 'should switch to original window if invoked not for current window' do\n      other_window = @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n      sleep 1\n      size = @session.within_window(other_window) do\n        win_size\n      end\n      expect(other_window.size).to eq(size)\n      expect(@session.current_window).to eq(orig_window)\n    end\n  end\n\n  describe '#resize_to' do\n    let!(:initial_size) { @session.current_window.size }\n\n    after do\n      @session.current_window.resize_to(*initial_size)\n      sleep 1\n    end\n\n    it 'should be able to resize window', requires: %i[windows js] do\n      width, height = initial_size\n      @session.current_window.resize_to(width - 100, height - 100)\n      sleep 1\n      expect(@session.current_window.size).to eq([width - 100, height - 100])\n    end\n\n    it 'should stay on current window if invoked not for current window', requires: %i[windows js] do\n      other_window = @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n\n      other_window.resize_to(600, 400)\n      expect(@session.current_window).to eq(orig_window)\n\n      @session.within_window(other_window) do\n        expect(@session.current_window.size).to eq([600, 400])\n      end\n    end\n  end\n\n  describe '#maximize' do\n    let! :initial_size do\n      @session.current_window.size\n    end\n\n    after do\n      @session.current_window.resize_to(*initial_size)\n      sleep 0.5\n    end\n\n    it 'should be able to maximize window', requires: %i[windows js] do\n      start_width, start_height = 400, 300\n      @session.current_window.resize_to(start_width, start_height)\n      sleep 0.5\n\n      @session.current_window.maximize\n      sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur\n\n      max_width, max_height = @session.current_window.size\n\n      # maximize behavior is window manage dependant, so just make sure it increases in size\n      expect(max_width).to be > start_width\n      expect(max_height).to be > start_height\n    end\n\n    it 'should stay on current window if invoked not for current window', requires: %i[windows js] do\n      other_window = @session.window_opened_by do\n        @session.find(:css, '#openWindow').click\n      end\n      other_window.resize_to(400, 300)\n      sleep 0.5\n      other_window.maximize\n      sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur\n\n      expect(@session.current_window).to eq(orig_window)\n      # Maximizing the browser affects all tabs so this may not be valid in real browsers\n      # expect(@session.current_window.size).to eq(initial_size)\n\n      ow_width, ow_height = other_window.size\n      expect(ow_width).to be > 400\n      expect(ow_height).to be > 300\n    end\n  end\n\n  describe '#fullscreen' do\n    let! :initial_size do\n      @session.current_window.size\n    end\n\n    after do\n      @session.current_window.resize_to(*initial_size)\n      sleep 1\n    end\n\n    it 'should be able to fullscreen the window' do\n      expect do\n        @session.current_window.fullscreen\n      end.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/windows_spec.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this\n# because of the methods being tested. In tests using Capybara this type of behavior should be implemented\n# using Capybara provided assertions with builtin waiting behavior.\n\nCapybara::SpecHelper.spec '#windows', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n    @session.find(:css, '#openTwoWindows').click\n\n    @session.document.synchronize(3, errors: [Capybara::CapybaraError]) do\n      raise Capybara::CapybaraError if @session.windows.size != 3\n    end\n  end\n\n  after do\n    (@session.windows - [@window]).each(&:close)\n    @session.switch_to_window(@window)\n  end\n\n  it 'should return objects of Capybara::Window class' do\n    expect(@session.windows.map { |window| window.instance_of?(Capybara::Window) }).to eq([true] * 3)\n  end\n\n  it 'should be able to switch to windows' do\n    sleep 1 # give windows enough time to fully load\n    titles = @session.windows.map do |window|\n      @session.within_window(window) { @session.title }\n    end\n    expect(titles).to match_array(['With Windows', 'Title of the first popup', 'Title of popup two']) # rubocop:disable RSpec/MatchArray\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/window/within_window_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#within_window', requires: [:windows] do\n  before do\n    @window = @session.current_window\n    @session.visit('/with_windows')\n    @session.find(:css, '#openTwoWindows').click\n\n    @session.document.synchronize(3, errors: [Capybara::CapybaraError]) do\n      raise Capybara::CapybaraError if @session.windows.size != 3\n    end\n  end\n\n  after do\n    (@session.windows - [@window]).each do |w|\n      @session.switch_to_window w\n      w.close\n    end\n    @session.switch_to_window(@window)\n  end\n\n  context 'with an instance of Capybara::Window' do\n    it 'should not invoke driver#switch_to_window when given current window' do\n      allow(@session.driver).to receive(:switch_to_window).and_call_original\n      @session.within_window @window do\n        expect(@session.title).to eq('With Windows')\n      end\n      expect(@session.driver).not_to have_received(:switch_to_window)\n    end\n\n    it 'should be able to switch to another window' do\n      window = (@session.windows - [@window]).first\n      @session.within_window window do\n        expect(@session).to have_title(/Title of the first popup|Title of popup two/)\n      end\n      expect(@session.title).to eq('With Windows')\n    end\n\n    it 'returns value from the block' do\n      window = (@session.windows - [@window]).first\n      value = @session.within_window window do\n        43252003274489856000\n      end\n      expect(value).to eq(43252003274489856000)\n    end\n\n    it 'should switch back if exception was raised inside block' do\n      window = (@session.windows - [@window]).first\n      expect do\n        @session.within_window(window) do\n          @session.within 'html' do\n            raise 'some error'\n          end\n        end\n      end.to raise_error(StandardError, 'some error')\n      expect(@session.current_window).to eq(@window)\n      expect(@session).to have_css('#doesNotOpenWindows')\n      expect(@session.send(:scopes)).to eq([nil])\n    end\n\n    it 'should leave correct scopes after execution in case of error', requires: %i[windows frames] do\n      window = (@session.windows - [@window]).first\n      expect do\n        @session.within_frame 'frameOne' do\n          @session.within_window(window) {}\n        end\n      end.to raise_error(Capybara::ScopeError)\n      expect(@session.current_window).to eq(@window)\n      expect(@session).to have_css('#doesNotOpenWindows')\n      expect(@session.send(:scopes)).to eq([nil])\n    end\n\n    it 'should raise error if closed window was passed' do\n      other_window = (@session.windows - [@window]).first\n      @session.within_window other_window do\n        other_window.close\n      end\n      expect do\n        @session.within_window(other_window) do\n          raise 'should not be invoked'\n        end\n      end.to raise_error(@session.driver.no_such_window_error)\n      expect(@session.current_window).to eq(@window)\n      expect(@session).to have_css('#doesNotOpenWindows')\n      expect(@session.send(:scopes)).to eq([nil])\n    end\n  end\n\n  context 'with lambda' do\n    it 'should find the div in another window' do\n      @session.within_window(-> { @session.title == 'Title of the first popup' }) do\n        expect(@session).to have_css('#divInPopupOne')\n      end\n    end\n\n    it 'should find divs in both windows' do\n      @session.within_window(-> { @session.title == 'Title of popup two' }) do\n        expect(@session).to have_css('#divInPopupTwo')\n      end\n      @session.within_window(-> { @session.title == 'Title of the first popup' }) do\n        expect(@session).to have_css('#divInPopupOne')\n      end\n      expect(@session.title).to eq('With Windows')\n    end\n\n    it 'should be able to nest within_window' do\n      @session.within_window(-> { @session.title == 'Title of popup two' }) do\n        expect(@session).to have_css('#divInPopupTwo')\n        @session.within_window(-> { @session.title == 'Title of the first popup' }) do\n          expect(@session).to have_css('#divInPopupOne')\n        end\n        expect(@session).to have_css('#divInPopupTwo')\n        expect(@session).not_to have_css('divInPopupOne')\n      end\n      expect(@session).not_to have_css('#divInPopupTwo')\n      expect(@session).not_to have_css('divInPopupOne')\n      expect(@session.title).to eq('With Windows')\n    end\n\n    it 'should work inside a normal scope' do\n      expect(@session).to have_css('#openWindow')\n      @session.within(:css, '#scope') do\n        @session.within_window(-> { @session.title == 'Title of the first popup' }) do\n          expect(@session).to have_css('#divInPopupOne')\n        end\n        expect(@session).to have_content('My scoped content')\n        expect(@session).not_to have_css('#openWindow')\n      end\n    end\n\n    it \"should raise error if window wasn't found\" do\n      expect do\n        @session.within_window(-> { @session.title == 'Invalid title' }) do\n          expect(@session).to have_css('#divInPopupOne')\n        end\n      end.to raise_error(Capybara::WindowError, 'Could not find a window matching block/lambda')\n      expect(@session.current_window).to eq(@window)\n      expect(@session).to have_css('#doesNotOpenWindows')\n      expect(@session.send(:scopes)).to eq([nil])\n    end\n\n    it 'returns value from the block' do\n      value = @session.within_window(-> { @session.title == 'Title of popup two' }) { 42 }\n      expect(value).to eq(42)\n    end\n\n    it 'should switch back if exception was raised inside block' do\n      expect do\n        @session.within_window(-> { @session.title == 'Title of popup two' }) do\n          raise 'some error'\n        end\n      end.to raise_error(StandardError, 'some error')\n      expect(@session.current_window).to eq(@window)\n      expect(@session.send(:scopes)).to eq([nil])\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/session/within_spec.rb",
    "content": "# frozen_string_literal: true\n\nCapybara::SpecHelper.spec '#within' do\n  before do\n    @session.visit('/with_scope')\n  end\n\n  context 'with CSS selector' do\n    it 'should click links in the given scope' do\n      @session.within(:css, '#for_bar li:first-child') do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should assert content in the given scope' do\n      @session.within(:css, '#for_foo') do\n        expect(@session).not_to have_content('First Name')\n      end\n      expect(@session).to have_content('First Name')\n    end\n\n    it 'should accept additional options' do\n      @session.within(:css, '#for_bar li', text: 'With Simple HTML') do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n\n    it 'should reload the node if the page is changed' do\n      @session.within(:css, '#for_foo') do\n        @session.visit('/with_scope_other')\n        expect(@session).to have_content('Different text')\n      end\n    end\n\n    it 'should reload multiple nodes if the page is changed' do\n      @session.within(:css, '#for_bar') do\n        @session.within(:css, 'form[action=\"/redirect\"]') do\n          @session.refresh\n          expect(@session).to have_content('First Name')\n        end\n      end\n    end\n\n    it 'should error if the page is changed and a matching node no longer exists' do\n      @session.within(:css, '#for_foo') do\n        @session.visit('/')\n        expect { @session.text }.to raise_error(StandardError)\n      end\n    end\n\n    it 'should pass scope element to the block' do\n      @session.within(:css, '#another_foo') do |scope|\n        expect(scope).to match_css('#another_foo')\n      end\n    end\n\n    it 'should scope click', requires: [:js] do\n      @session.within(:css, '#another_foo') do |scope|\n        @session.click\n        expect(scope).to have_text('I was clicked')\n      end\n    end\n  end\n\n  context 'with XPath selector' do\n    it 'should click links in the given scope' do\n      @session.within(:xpath, \"//div[@id='for_bar']//li[contains(.,'With Simple HTML')]\") do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with the default selector' do\n    it 'should use XPath' do\n      @session.within(\"//div[@id='for_bar']//li[contains(.,'With Simple HTML')]\") do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with Node rather than selector' do\n    it 'should click links in the given scope' do\n      node_of_interest = @session.find(:css, '#for_bar li', text: 'With Simple HTML')\n\n      @session.within(node_of_interest) do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with the default selector set to CSS' do\n    before { Capybara.default_selector = :css }\n\n    after { Capybara.default_selector = :xpath }\n\n    it 'should use CSS' do\n      @session.within('#for_bar li', text: 'With Simple HTML') do\n        @session.click_link('Go')\n      end\n      expect(@session).to have_content('Bar')\n    end\n  end\n\n  context 'with nested scopes' do\n    it 'should respect the inner scope' do\n      @session.within(\"//div[@id='for_bar']\") do\n        @session.within(\".//li[contains(.,'Bar')]\") do\n          @session.click_link('Go')\n        end\n      end\n      expect(@session).to have_content('Another World')\n    end\n\n    it 'should respect the outer scope' do\n      @session.within(\"//div[@id='another_foo']\") do\n        @session.within(\".//li[contains(.,'With Simple HTML')]\") do\n          @session.click_link('Go')\n        end\n      end\n      expect(@session).to have_content('Hello world')\n    end\n  end\n\n  it 'should raise an error if the scope is not found on the page' do\n    expect do\n      @session.within(\"//div[@id='doesnotexist']\") do\n      end\n    end.to raise_error(Capybara::ElementNotFound)\n  end\n\n  it 'should restore the scope when an error is raised' do\n    expect do\n      @session.within(\"//div[@id='for_bar']\") do\n        expect do\n          expect do\n            @session.within(\".//div[@id='doesnotexist']\") do\n            end\n          end.to raise_error(Capybara::ElementNotFound)\n        end.not_to change { @session.has_xpath?(\".//div[@id='another_foo']\") }.from(false)\n      end\n    end.not_to change { @session.has_xpath?(\".//div[@id='another_foo']\") }.from(true)\n  end\n\n  it 'should fill in a field and click a button' do\n    @session.within(\"//li[contains(.,'Bar')]\") do\n      @session.click_button('Go')\n    end\n    expect(extract_results(@session)['first_name']).to eq('Peter')\n    @session.visit('/with_scope')\n    @session.within(\"//li[contains(.,'Bar')]\") do\n      @session.fill_in('First Name', with: 'Dagobert')\n      @session.click_button('Go')\n    end\n    expect(extract_results(@session)['first_name']).to eq('Dagobert')\n  end\n\n  it 'should have #within_element as an alias' do\n    expect(Capybara::Session.instance_method(:within)).to eq Capybara::Session.instance_method(:within_element)\n    @session.within_element(:css, '#for_foo') do\n      expect(@session).not_to have_content('First Name')\n    end\n  end\nend\n\nCapybara::SpecHelper.spec '#within_fieldset' do\n  before do\n    @session.visit('/fieldsets')\n  end\n\n  it 'should restrict scope to a fieldset given by id' do\n    @session.within_fieldset('villain_fieldset') do\n      @session.fill_in('Name', with: 'Goldfinger')\n      @session.click_button('Create')\n    end\n    expect(extract_results(@session)['villain_name']).to eq('Goldfinger')\n  end\n\n  it 'should restrict scope to a fieldset given by legend' do\n    @session.within_fieldset('Villain') do\n      @session.fill_in('Name', with: 'Goldfinger')\n      @session.click_button('Create')\n    end\n    expect(extract_results(@session)['villain_name']).to eq('Goldfinger')\n  end\nend\n\nCapybara::SpecHelper.spec '#within_table' do\n  before do\n    @session.visit('/tables')\n  end\n\n  it 'should restrict scope to a fieldset given by id' do\n    @session.within_table('girl_table') do\n      @session.fill_in('Name', with: 'Christmas')\n      @session.click_button('Create')\n    end\n    expect(extract_results(@session)['girl_name']).to eq('Christmas')\n  end\n\n  it 'should restrict scope to a fieldset given by legend' do\n    @session.within_table('Villain') do\n      @session.fill_in('Name', with: 'Quantum')\n      @session.click_button('Create')\n    end\n    expect(extract_results(@session)['villain_name']).to eq('Quantum')\n  end\nend\n"
  },
  {
    "path": "lib/capybara/spec/spec_helper.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rspec'\nrequire 'rspec/expectations'\nrequire 'capybara'\nrequire 'capybara/rspec' # Required here instead of in rspec_spec to avoid RSpec deprecation warning\nrequire 'capybara/spec/test_app'\nrequire 'nokogiri'\n\nCapybara.save_path = File.join(Dir.pwd, 'save_path_tmp')\n\nmodule Capybara\n  module SpecHelper\n    class << self\n      def configure(config)\n        config.filter_run_excluding requires: method(:filter).to_proc\n        config.before { Capybara::SpecHelper.reset! }\n        config.after { Capybara::SpecHelper.reset! }\n        config.shared_context_metadata_behavior = :apply_to_host_groups\n      end\n\n      def reset!\n        Capybara.app = TestApp\n        Capybara.app_host = nil\n        Capybara.default_selector = :xpath\n        Capybara.default_max_wait_time = 1\n        Capybara.default_retry_interval = 0.01\n        Capybara.ignore_hidden_elements = true\n        Capybara.exact = false\n        Capybara.raise_server_errors = true\n        Capybara.visible_text_only = false\n        Capybara.match = :smart\n        Capybara.enable_aria_label = false\n        Capybara.enable_aria_role = false\n        Capybara.default_set_options = {}\n        Capybara.disable_animation = false\n        Capybara.test_id = nil\n        Capybara.predicates_wait = true\n        Capybara.default_normalize_ws = false\n        Capybara.use_html5_parsing = !ENV['HTML5_PARSING'].nil?\n        Capybara.w3c_click_offset = true\n        reset_threadsafe\n      end\n\n      def filter(requires, metadata)\n        if requires && metadata[:capybara_skip]\n          requires.any? do |require|\n            metadata[:capybara_skip].include?(require)\n          end\n        else\n          false\n        end\n      end\n\n      def spec(name, *options, &block)\n        @specs ||= []\n        @specs << [name, options, block]\n      end\n\n      def run_specs(session, name, **options, &filter_block)\n        specs = @specs\n        RSpec.describe Capybara::Session, name, options do\n          include Capybara::SpecHelper\n          include Capybara::RSpecMatchers\n\n          before do |example|\n            @session = session\n            instance_exec(example, &filter_block) if filter_block\n          end\n\n          after do\n            session.reset_session!\n          end\n\n          before :each, :psc do\n            SpecHelper.reset_threadsafe(bool: true, session: session)\n          end\n\n          after psc: true do\n            SpecHelper.reset_threadsafe(session: session)\n          end\n\n          before :each, :exact_false do\n            Capybara.exact = false\n          end\n\n          specs.each do |spec_name, spec_options, block|\n            describe spec_name, *spec_options do\n              class_eval(&block)\n            end\n          end\n        end\n      end\n\n      def reset_threadsafe(bool: false, session: nil)\n        # Work around limit on when threadsafe can be changed\n        Capybara::Session.class_variable_set(:@@instance_created, false) # rubocop:disable Style/ClassVars\n        Capybara.threadsafe = bool\n        session = session.current_session if session.respond_to?(:current_session)\n        session&.instance_variable_set(:@config, nil)\n      end\n    end\n\n    def silence_stream(stream)\n      old_stream = stream.dup\n      stream.reopen(RbConfig::CONFIG['host_os'].match?(/rmswin|mingw/) ? 'NUL:' : '/dev/null')\n      stream.sync = true\n      yield\n    ensure\n      stream.reopen(old_stream)\n    end\n\n    def quietly(&block)\n      silence_stream($stdout) do\n        silence_stream($stderr, &block)\n      end\n    end\n\n    def extract_results(session)\n      expect(session).to have_xpath(\"//pre[@id='results']\")\n      perms = [(::Sinatra::IndifferentHash if defined? ::Sinatra::IndifferentHash)].compact\n      results = Capybara::HTML(session.body).xpath(\"//pre[@id='results']\").first.inner_html.lstrip\n      YAML.safe_load results, permitted_classes: perms\n    end\n\n    def extract_content_type(session)\n      expect(session).to have_xpath(\"//pre[@id='content_type']\")\n      Capybara::HTML(session.body).xpath(\"//pre[@id='content_type']\").first.text\n    end\n\n    def be_an_invalid_element_error(session)\n      satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }\n    end\n\n    def with_os_path_separators(path)\n      Gem.win_platform? ? path.to_s.tr('/', '\\\\') : path.to_s\n    end\n  end\nend\n\nDir[\"#{File.dirname(__FILE__)}/session/**/*.rb\"].each { |file| require_relative file }\n"
  },
  {
    "path": "lib/capybara/spec/test_app.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'sinatra/base'\nrequire 'tilt/erb'\nrequire 'rack'\nrequire 'yaml'\n\nclass TestApp < Sinatra::Base\n  class TestAppError < Exception; end # rubocop:disable Lint/InheritException\n\n  class TestAppOtherError < Exception # rubocop:disable Lint/InheritException\n    def initialize(string1, msg)\n      super()\n      @something = string1\n      @message = msg\n    end\n  end\n  set :root, File.dirname(__FILE__)\n  set :static, true\n  set :raise_errors, true\n  set :show_exceptions, false\n  set :host_authorization, { permitted_hosts: [] }\n\n  # Also check lib/capybara/spec/views/*.erb for pages not listed here\n\n  get '/' do\n    response.set_cookie('capybara', value: 'root cookie', domain: request.host, path: request.path)\n    'Hello world! <a href=\"with_html\">Relative</a>'\n  end\n\n  get '/foo' do\n    'Another World'\n  end\n\n  get '/redirect' do\n    redirect '/redirect_again'\n  end\n\n  get '/redirect_with_fragment' do\n    redirect '/landed#with_fragment'\n  end\n\n  get '/redirect_again' do\n    redirect '/landed'\n  end\n\n  post '/redirect_307' do\n    redirect '/landed', 307\n  end\n\n  post '/redirect_308' do\n    redirect '/landed', 308\n  end\n\n  get '/referer_base' do\n    '<a href=\"/get_referer\">direct link</a>' \\\n      '<a href=\"/redirect_to_get_referer\">link via redirect</a>' \\\n      '<form action=\"/get_referer\" method=\"get\"><input type=\"submit\"></form>'\n  end\n\n  get '/redirect_to_get_referer' do\n    redirect '/get_referer'\n  end\n\n  get '/get_referer' do\n    request.referer.nil? ? 'No referer' : \"Got referer: #{request.referer}\"\n  end\n\n  get '/host' do\n    \"Current host is #{request.scheme}://#{request.host}:#{request.port}\"\n  end\n\n  get '/redirect/:times/times' do\n    times = params[:times].to_i\n    if times.zero?\n      'redirection complete'\n    else\n      redirect \"/redirect/#{times - 1}/times\"\n    end\n  end\n\n  get '/landed' do\n    'You landed'\n  end\n\n  post '/landed' do\n    \"You post landed: #{params.dig(:form, 'data')}\"\n  end\n\n  get '/with-quotes' do\n    %q(\"No,\" he said, \"you can't do that.\")\n  end\n\n  get '/form/get' do\n    %(<pre id=\"results\">#{params[:form].to_yaml}</pre>)\n  end\n\n  post '/relative' do\n    %(<pre id=\"results\">#{params[:form].to_yaml}</pre>)\n  end\n\n  get '/favicon.ico' do\n    nil\n  end\n\n  post '/redirect' do\n    redirect '/redirect_again'\n  end\n\n  delete '/delete' do\n    'The requested object was deleted'\n  end\n\n  get '/delete' do\n    'Not deleted'\n  end\n\n  get '/redirect_back' do\n    redirect back\n  end\n\n  get '/redirect_secure' do\n    redirect \"https://#{request.host}:#{request.port}/host\"\n  end\n\n  get '/slow_response' do\n    sleep 2\n    'Finally!'\n  end\n\n  get '/set_cookie' do\n    cookie_value = 'test_cookie'\n    response.set_cookie('capybara', cookie_value)\n    \"Cookie set to #{cookie_value}\"\n  end\n\n  get '/get_cookie' do\n    request.cookies['capybara']\n  end\n\n  get '/get_header' do\n    env['HTTP_FOO']\n  end\n\n  get '/get_header_via_redirect' do\n    redirect '/get_header'\n  end\n\n  get '/error' do\n    raise TestAppError, 'some error'\n  end\n\n  get '/other_error' do\n    raise TestAppOtherError.new('something', 'other error')\n  end\n\n  get '/load_error' do\n    raise LoadError\n  end\n\n  get '/with.*html' do\n    erb :with_html, locals: { referrer: request.referrer }\n  end\n\n  get '/with_title' do\n    <<-HTML\n      <!DOCTYPE html>\n      <html lang=\"en\">\n        <head>\n          <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n          <title>#{params[:title] || 'Test Title'}</title>\n        </head>\n\n        <body>\n          <svg><title>abcdefg</title></svg>\n        </body>\n      </html>\n    HTML\n  end\n\n  get '/with_iframe' do\n    <<-HTML\n      <!DOCTYPE html>\n      <html lang=\"en\">\n        <head>\n          <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n          <title>Test with Iframe</title>\n        </head>\n\n        <body>\n          <iframe src=\"#{params[:url]}\" id=\"#{params[:id]}\"></iframe>\n        </body>\n      </html>\n    HTML\n  end\n\n  get '/base/with_base' do\n    <<-HTML\n      <!DOCTYPE html>\n      <html>\n        <head>\n          <base href=\"/\">\n          <title>Origin</title>\n        </head>\n        <body>\n          <a href=\"with_title\">Title page</a>\n          <a href=\"?a=3\">Bare query</a>\n        </body>\n      </html>\n    HTML\n  end\n\n  get '/base/with_other_base' do\n    <<-HTML\n      <!DOCTYPE html>\n      <html>\n        <head>\n          <base href=\"/base/\">\n          <title>Origin</title>\n        </head>\n        <body>\n          <a href=\"with_title\">Title page</a>\n          <a href=\"?a=3\">Bare query</a>\n        </body>\n      </html>\n    HTML\n  end\n\n  get '/csp' do\n    response.headers['Content-Security-Policy'] = \"default-src 'none'; connect-src 'self'; base-uri 'none'; font-src 'self'; img-src 'self' data:; object-src 'none'; script-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; style-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; form-action 'self';\"\n    <<-HTML\n      <!DOCTYPE html>\n      <html lang=\"en\">\n        <head>\n          <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n          <title>CSP</title>\n        </head>\n\n        <body>\n          <div>CSP</div>\n        </body>\n      </html>\n    HTML\n  end\n\n  get '/download.csv' do\n    content_type 'text/csv'\n    'This, is, comma, separated' \\\n      'Thomas, Walpole, was , here'\n  end\n\n  get %r{/apple-touch-.*\\.png/} do\n    halt(404)\n  end\n\n  get '/:view' do |view|\n    view_template = \"#{__dir__}/views/#{view}.erb\"\n    has_layout = File.exist?(view_template) && File.open(view_template) { |f| f.first.downcase.include?('doctype') }\n    erb view.to_sym, locals: { referrer: request.referrer }, layout: !has_layout\n  end\n\n  post '/form' do\n    self.class.form_post_count += 1\n    %(\n      <pre id=\"content_type\">#{request.content_type}</pre>\n      <pre id=\"results\">#{params.fetch(:form, {}).merge('post_count' => self.class.form_post_count).to_yaml}</pre>\n    )\n  end\n\n  post '/upload_empty' do\n    if params[:form][:file].nil?\n      \"Successfully ignored empty file field. Content type was #{request.content_type}\"\n    else\n      'Something went wrong.'\n    end\n  end\n\n  post '/upload' do\n    buffer = []\n    buffer << \"Content-type: #{params.dig(:form, :document, :type)}\"\n    buffer << \"File content: #{params.dig(:form, :document, :tempfile).read}\"\n    buffer.join(' | ')\n  rescue StandardError\n    'No file uploaded'\n  end\n\n  post '/upload_multiple' do\n    docs = params.dig(:form, :multiple_documents)\n    buffer = [docs.size.to_s]\n    docs.each do |doc|\n      buffer << \"Content-type: #{doc[:type]}\"\n      buffer << \"File content: #{doc[:tempfile].read}\"\n    end\n    buffer.join(' | ')\n  rescue StandardError\n    'No files uploaded'\n  end\n\n  class << self\n    attr_accessor :form_post_count\n  end\n\n  @form_post_count = 0\nend\n\nRack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__\n"
  },
  {
    "path": "lib/capybara/spec/views/animated.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_animation</title>\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script>\n      $(document).on('contextmenu', function(e){ e.preventDefault(); });\n    </script>\n    <style>\n      div {\n        width: 400px;\n        height: 400px;\n        position: absolute;\n      }\n      #obscured {\n        z-index: 1;\n        background-color: red;\n      }\n      #cover {\n        z-index: 2;\n        background-color: blue;\n      }\n      #offscreen {\n        top: 2000px;\n        left: 2000px;\n        background-color: green;\n      }\n      #offscreen_wrapper {\n        top: 2000px;\n        left: 2000px;\n        overflow-x: scroll;\n        background-color: yellow;\n      }\n    </style>\n  </head>\n\n  <body id=\"with_animation\">\n    <div id=\"obscured\">\n      <input id=\"obscured_input\"/>\n    </div>\n    <div id=\"cover\"></div>\n    <div id=\"offscreen_wrapper\">\n      <div id=\"offscreen\"></div>\n    </div>\n  </body>\n\n  <iframe id=\"frameOne\" src=\"/frame_one\"></iframe>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/buttons.erb",
    "content": "\n<h1>Buttons</h1>\n<button>Click me!</button>\n<button id=\"click_me_123\">Click me by id!</button>\n<button value=\"click_me\">Click me by value!</button>\n"
  },
  {
    "path": "lib/capybara/spec/views/fieldsets.erb",
    "content": "\n<form action=\"/form\" method=\"post\">\n  <fieldset id=\"agent_fieldset\">\n    <legend>Agent</legend>\n  \n    <p>\n      <label for=\"form_agent_name\">Name</label>\n      <input type=\"text\" name=\"form[agent_name]\" value=\"James\" id=\"form_agent_name\"/>\n    </p>\n  \n    <p>\n      <input type=\"submit\" value=\"Create\"/>\n    </p>\n  </fieldset>\n</form>\n\n<form action=\"/form\" method=\"post\">\n  <fieldset id=\"villain_fieldset\">\n    <legend>Villain</legend>\n  \n    <p>\n      <label for=\"form_villain_name\">Name</label>\n      <input type=\"text\" name=\"form[villain_name]\" value=\"Ernst\" id=\"form_villain_name\"/>\n    </p>\n  \n    <p>\n      <input type=\"submit\" value=\"Create\"/>\n    </p>\n  </fieldset>\n</form>\n"
  },
  {
    "path": "lib/capybara/spec/views/form.erb",
    "content": "<h1>Form</h1>\n\n<button type=\"button\" tabindex=\"1\">A Button</button>\n\n<label>\n  An Input\n  <input type=\"text\" tabindex=\"2\">\n</label>\n\n<form action=\"/form\" method=\"post\" novalidate>\n\n  <p>\n    <label for=\"form_title\">Title</label>\n    <select name=\"form[title]\" id=\"form_title\" class=\"title\" tabindex=\"3\">\n      <option class=\"title\">Mrs</option>\n      <option class=\"title\">Mr</option>\n      <option>Miss</option>\n      <option disabled=\"disabled\">Other</option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"customer_name\">Customer Name\n      <input type=\"text\" name=\"form[customer_name]\" value=\"Blah\" id=\"customer_name\" disabled=\"disabled\"/>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"customer_email\">Customer Email\n      <input type=\"text\" name=\"form[customer_email]\" value=\"ben@ben.com\" id=\"customer_email\"/>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"customer_other_email\">Customer Other Email\n      <input type=\"text\" name=\"form[customer_other_email]\" value=\"notben@notben.com\" id=\"customer_other_email\"/>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_other_title\">Other title</label>\n    <select name=\"form[other_title]\" id=\"form_other_title\">\n      <option>Mrs</option>\n      <option>Mr</option>\n      <option>Miss</option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"form_first_name\">\n      First Name\n      <input type=\"text\" name=\"form[first_name]\" value=\"John\" id=\"form_first_name\" placeholder=\"FirstName\"/>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_last_name\">Last Name</label>\n    <input type=\"text\" name=\"form[last_name]\" value=\"Smith\" id=\"form_last_name\"/>\n  </p>\n\n  <p>\n    <label for=\"form_name_explanation\">Explanation of Name</label>\n    <textarea name=\"form[name_explanation]\" id=\"form_name_explanation\"></textarea>\n  </p>\n\n  <p>\n    <label for=\"form_name\">Name</label>\n    <input type=\"text\" name=\"form[name]\" value=\"John Smith\" id=\"form_name\"/>\n  </p>\n\n  <p>\n    <label for=\"form_age\">Age</label>\n    <input type=\"range\" name=\"form[age]\" value=\"18\" min=\"13\" max=\"100\" step=\"0.5\" id=\"form_age\"/>\n  </p>\n\n  <p>\n    <label for=\"form_schmooo\">Schmooo</label>\n    <input type=\"schmooo\" name=\"form[schmooo]\" value=\"This is Schmooo!\" id=\"form_schmooo\"/>\n  </p>\n\n  <p>\n    <label>Street<br/>\n      <input type=\"text\" maxlength=\"\" name=\"form[street]\" value=\"Sesame street 66\"/>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_phone\">Phone</label>\n    <input name=\"form[phone]\" value=\"+1 555 7021\" id=\"form_phone\"/>\n  </p>\n\n  <p>\n    <label for=\"form_password\">Password</label>\n    <input type=\"password\" name=\"form[password]\" value=\"seeekrit\" id=\"form_password\"/>\n  </p>\n\n  <p>\n    <label for=\"form_terms_of_use\">Terms of Use</label>\n    <input type=\"hidden\" name=\"form[terms_of_use]\" value=\"0\" id=\"form_terms_of_use_default\">\n    <input type=\"checkbox\" name=\"form[terms_of_use]\" value=\"1\" id=\"form_terms_of_use\">\n  </p>\n\n  <p>\n    <label for=\"form_image\">Image</label>\n    <input type=\"file\" name=\"form[image]\" id=\"form_image\"/>\n  </p>\n\n  <p>\n    <label for=\"form_hidden_image\">Hidden Image</label>\n    <input type=\"file\" name=\"form[hidden_image]\" id=\"form_hidden_image\" style=\"display: none\"/>\n  </p>\n\n  <p>\n    <input type=\"hidden\" name=\"form[token]\" value=\"12345\" id=\"form_token\"/>\n  </p>\n\n  <p>\n    <label for=\"form_locale\">Locale</label>\n    <select name=\"form[locale]\" id=\"form_locale\">\n      <option value=\"sv\">Swedish</option>\n      <option selected=\"selected\" value=\"en\">English</option>\n      <option value=\"fi\">Finnish</option>\n      <option value=\"no\">Norwegian</option>\n      <option value=\"jo\">John's made-up language</option>\n      <option value=\"jbo\"> Lojban </option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"form_region\">Region</label>\n    <select name=\"form[region]\" id=\"form_region\">\n      <option>Sweden</option>\n      <option selected=\"selected\">Norway</option>\n      <option>Finland</option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"form_city\">City</label>\n    <select name=\"form[city]\" id=\"form_city\">\n      <option>London</option>\n      <option>Stockholm</option>\n      <option>Paris</option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"form_zipcode\">Zipcode</label>\n    <input type=\"text\" maxlength=\"5\" name=\"form[zipcode]\" id=\"form_zipcode\" pattern=\"[0-9]{5,9}\" />\n  </p>\n\n  <p>\n    <input maxlength=\"35\" id=\"long_length\" />\n  </p>\n\n  <p>\n    <label for=\"form_tendency\">Tendency</label>\n    <select name=\"form[tendency]\" id=\"form_tendency\"></select>\n  </p>\n\n  <p>\n    <label for=\"form_description\">Description</label></br>\n    <textarea name=\"form[description]\" id=\"form_description\">Descriptive text goes here</textarea>\n  <p>\n\n  <p>\n    <label for=\"form_newline\">NewLine</label></br>\n    <textarea name=\"form[newline]\" id=\"form_newline\">\n\nNew line after and before textarea tag\n</textarea>\n  </p>\n\n  <p>\n    <input type=\"radio\" name=\"form[gender]\" value=\"male\" id=\"gender_male\"/>\n    <label for=\"gender_male\">Male</label>\n    <input type=\"radio\" name=\"form[gender]\" value=\"female\" id=\"gender_female\" checked=\"checked\"/>\n    <label for=\"gender_female\">Female</label>\n    <input type=\"radio\" name=\"form[gender]\" value=\"both\" id=\"gender_both\" readonly=\"readonly\"/>\n    <label for=\"gender_both\">Both</label>\n  </p>\n\n  <p>\n    <input type=\"radio\" name=\"form[party]\" value=\"democrat\" id=\"party_democrat\" style=\"display:none\"/>\n    <label for=\"party_democrat\">Democrat</label>\n    <input type=\"radio\" name=\"form[party]\" value=\"republican\" id=\"party_republican\" style=\"display:none\"/>\n    <label for=\"party_republican\">Republican</label>\n    <input type=\"radio\" name=\"form[party]\" value=\"independent\" id=\"party_independent\" checked=\"checked\" style=\"display:none\"/>\n    <label for=\"party_independent\">Independent</label>\n  </p>\n\n  <p>\n    <input type=\"checkbox\" id=\"no_attr_value_checked\" value=\"1\" checked/>\n  </p>\n\n  <p>\n    <input type=\"checkbox\" value=\"dog\" name=\"form[pets][]\" id=\"form_pets_dog\" checked=\"checked\"/>\n    <label for=\"form_pets_dog\">Dog</label>\n    <input type=\"checkbox\" value=\"cat\" name=\"form[pets][]\" id=\"form_pets_cat\"/>\n    <label for=\"form_pets_cat\">Cat</label>\n    <input type=\"checkbox\" value=\"hamster\" name=\"form[pets][]\" id=\"form_pets_hamster\" checked=\"checked\"/>\n    <label for=\"form_pets_hamster\">Hamster</label>\n  </p>\n\n  <p>\n    <input type=\"checkbox\" value=\"jaguar\" name=\"form[cars][]\" id=\"form_cars_jaguar\" checked=\"checked\" style=\"display: none\"/>\n    <label for=\"form_cars_jaguar\">Jaguar</label>\n    <input type=\"checkbox\" value=\"tesla\" name=\"form[cars][]\" id=\"form_cars_tesla\" style=\"display: none\"/>\n    <label for=\"form_cars_tesla\">Tesla</label>\n    <input type=\"checkbox\" value=\"ferrari\" name=\"form[cars][]\" id=\"form_cars_ferrari\" checked=\"checked\" style=\"display: none\"/>\n    <label for=\"form_cars_ferrari\">Ferrari</label>\n    <input type=\"checkbox\" value=\"pagani\" name=\"form[cars][]\" id=\"form_cars_pagani\" style=\"position: absolute; left: -9999px\"/>\n    <label for=\"form_cars_pagani\">Pagani</label>\n    <div style=\"position: relative;\">\n      <input type=\"checkbox\" value=\"bugatti\" name=\"form[cars][]\" id=\"form_cars_bugatti\"/>\n      <div style=\"position: absolute; top: 0; right: 0; bottom: 0; left: 0; background-color: #fff;\">\n        <label for=\"form_cars_bugatti\">Bugatti</label>\n      </div>\n    </div>\n    <input type=\"checkbox\" value=\"ariel\" name=\"form[cars][]\" id=\"form_cars_ariel\" style=\"display: none\"/>\n    <input type=\"checkbox\" value=\"porsche\" name=\"form[cars][]\" id=\"form_cars_porsche\" checked=\"checked\" style=\"display: none\"/>\n    <label>\n      McLaren\n      <input type=\"checkbox\" value=\"mclaren\" name=\"form[cars][]\" id=\"form_cars_mclaren\" style=\"display: none\"/>\n    </label>\n    <label>\n      Koenigsegg\n      <input type=\"checkbox\" value=\"koenigsegg\" name=\"form[cars][]\" id=\"form_cars_koenigsegg\" checked=\"checked\" style=\"display: none\"/>\n    </label>\n    <input type=\"checkbox\" value=\"maserati\" name=\"form[cars][]\" id=\"form_cars_maserati\" disabled=\"disabled\"/>\n    <label for=\"form_cars_maserati\">Maserati</label>\n    <input type=\"checkbox\" value=\"lotus\" name=\"form[cars][]\" id=\"form_cars_lotus\" style=\"display: none\"/>\n    <label for=\"form_cars_lotus\"><a href=\"#\" onclick=\"return false;\">Link here</a>Lotus</label>\n  </p>\n\n  <p>\n    <input type=\"text\" name=\"form[manufacturer]\" list=\"manufacturers\" id=\"manufacturer\"/>\n    <datalist id=\"manufacturers\">\n      <option value=\"Jaguar\">J</option>\n      <option value=\"Audi\">\n      <option value=\"Mercedes\" disabled>\n    </datalist>\n  </p>\n\n  <p>\n    <input type=\"checkbox\" name=\"form[valueless_checkbox]\" id=\"valueless_checkbox\" checked=\"checked\"/>\n    <label for=\"valueless_checkbox\">Valueless Checkbox</label>\n    <input type=\"radio\" name=\"form[valueless_radio]\" id=\"valueless_radio\" checked=\"checked\"/>\n    <label for=\"valueless_radio\">Valueless Radio</label>\n  </p>\n\n  <p>\n    <label for=\"form_languages\">Languages</label>\n    <select name=\"form[languages][]\" id=\"form_languages\" multiple=\"multiple\">\n      <option>Ruby</option>\n      <option>SQL</option>\n      <option>HTML</option>\n      <option>Javascript</option>\n    </select>\n  </p>\n\n  <p>\n    <label for=\"form_underwear\">Underwear</label>\n    <select name=\"form[underwear][]\" id=\"form_underwear\" multiple=\"multiple\">\n      <option selected=\"selected\">Boxerbriefs</option>\n      <option>Boxers</option>\n      <option selected=\"selected\">Briefs</option>\n      <option selected=\"selected\">Commando</option>\n      <option selected=\"selected\">Frenchman's Pantalons</option>\n      <option selected=\"selected\" value=\"thermal\">Long Johns</option>\n    </select>\n  </p>\n\n  <!-- invisible select and options -->\n  <p style=\"display: none\">\n    <label for=\"form_icecream\">Icecream</label>\n    <select name=\"form[icecream]\" id=\"form_icecream\">\n      <option selected=\"selected\">Chocolate</option>\n      <option>Vanilla</option>\n      <option>Strawberry</option>\n    </select>\n  </p>\n\n  <!-- invisible multiselect and options -->\n  <p style=\"display: none\">\n    <label for=\"form_dessert\">Dessert</label>\n    <select name=\"form[dessert]\" id=\"form_dessert\" multiple=\"multiple\">\n      <option selected=\"selected\">Pudding</option>\n      <option>Lava cake</option>\n      <option selected=\"selected\">Tiramisu</option>\n      <option>Panna cotta</option>\n    </select>\n  </p>\n\n  <!-- visible select with invisible selected option (which some browsers may treat as visible) -->\n  <p>\n    <label for=\"form_sorbet\">Sorbet</label>\n    <select name=\"form[sorbet]\" id=\"form_sorbet\">\n      <option>Chocolate</option>\n      <option selected=\"selected\" style=\"display: none\">Vanilla</option>\n      <option>Strawberry</option>\n    </select>\n  </p>\n\n  <!-- visible multiselect with invisible selected options (which some browsers may treat as visible) -->\n  <p>\n    <label for=\"form_cake\">Cake</label>\n    <select name=\"form[cake]\" id=\"form_cake\" multiple=\"multiple\">\n      <option>Butter Cake</option>\n      <option selected=\"selected\" style=\"display: none\">Chocolate Cake</option>\n      <option>Strawberry Cake</option>\n      <option selected=\"selected\" style=\"display: none\">Sponge Cake</option>\n    </select>\n  </p>\n\n  <p>\n    <span>First address<span>\n    <label for='address1_street'>Street</label>\n    <input type=\"text\" name=\"form[addresses][][street]\" value=\"\" id=\"address1_street\">\n\n    <label for='address1_city'>City</label>\n    <input type=\"text\" name=\"form[addresses][][city]\" value=\"\" id=\"address1_city\">\n\n    <label for='address1_country'>Country</label>\n    <select name=\"form[addresses][][country]\" id=\"address1_country\">\n      <option selected>France</option>\n      <option>Ukraine</option>\n    </select>\n  </p>\n\n  <p>\n    <span>Second address<span>\n    <label for='address2_street'>Street</label>\n    <input type=\"text\" name=\"form[addresses][][street]\" value=\"\" id=\"address2_street\">\n\n    <label for='address2_city'>City</label>\n    <input type=\"text\" name=\"form[addresses][][city]\" value=\"\" id=\"address2_city\">\n\n    <label for='address2_country'>Country</label>\n    <select name=\"form[addresses][][country]\" id=\"address2_country\">\n      <option>France</option>\n      <option selected>Ukraine</option>\n    </select>\n  </p>\n\n  <div style=\"display:none;\">\n    <label for=\"form_first_name_hidden\">\n      Super Secret\n      <input type=\"text\" name=\"form[super_secret]\" value=\"test123\" id=\"form_super_secret\"/>\n    </label>\n  </div>\n\n  <p>\n    <label for=\"form_disabled_text_field\">\n      Disabled Text Field\n      <input type=\"text\" name=\"form[disabled_text_field]\" value=\"Should not see me\" id=\"form_disabled_text_field\" disabled=\"disabled\" />\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_textarea\">\n      Disabled Textarea\n      <textarea name=\"form[disabled_textarea]\" value=\"Should not see me\" id=\"form_disabled_textarea\" disabled=\"disabled\"></textarea>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_checkbox\">\n      Disabled Checkbox\n      <input type=\"checkbox\" name=\"form[disabled_checkbox]\" value=\"Should not see me\" id=\"form_disabled_checkbox\" checked=\"checked\" disabled=\"disabled\" />\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_unchecked_checkbox\">\n      Disabled Unchecked Checkbox\n      <input type=\"checkbox\" name=\"form[disabled_unchecked_checkbox]\" value=\"Should not see me\" id=\"form_disabled_unchecked_checkbox\" disabled=\"disabled\" />\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_radio\">\n      Disabled Radio\n      <input type=\"radio\" name=\"form[disabled_radio]\" value=\"Should not see me\" id=\"form_disabled_radio\" checked=\"checked\" disabled=\"disabled\" />\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_select\">\n      Disabled Select\n      <select name=\"form[disabled_select]\" id=\"form_disabled_select\" disabled=\"disabled\">\n        <option value=\"Should not see me\" selected=\"selected\">Should not see me</option>\n        <optgroup>\n          <option value=\"Disabled too\">Disabled too</option>\n        </optgroup>\n      </select>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_select2\">\n      Disabled Select 2\n      <select name=\"form[disabled_select2]\" id=\"form_disabled_select2\" disabled>\n        <option value=\"Should not see me\" selected=\"selected\">Should not see me</option>\n      </select>\n    </label>\n  </p>\n\n  <p>\n    <label for=\"form_disabled_file\">\n      Disabled File\n      <input type=\"file\" name=\"form[disabled_file]\" value=\"/should/not/see/me\" id=\"form_disabled_file\" disabled=\"disabled\" />\n    </label>\n  </p>\n\n  <fieldset>\n    <input name=\"form[enabled_fieldset_child]\" id=\"form_enabled_fieldset_child\"/>\n  </fieldset>\n\n  <fieldset disabled=\"disabled\" id=\"form_disabled_fieldset\">\n    <legend>Disabled Child</legend>\n    <input name=\"form[disabled_fieldset_child]\" id=\"form_disabled_fieldset_child\"/>\n    <select>\n      <option>Disabled Child Option</option>\n    </select>\n  </fieldset>\n\n  <fieldset disabled=\"disabled\">\n    <legend>\n      Nested Disabled\n      <input type=\"checkbox\" name=\"form[disabled_fieldeset_legend_child]\" id=\"form_disabled_fieldset_legend_child\"/>\n    </legend>\n    <legend>\n      Another WLegend\n      <input type=\"checkbox\" name=\"form[disabled_fieldeset_second_legend_child]\" id=\"form_disabled_fieldset_second_legend_child\"/>\n    </legend>\n    <fieldset>\n      <legend>\n        Disabled?\n        <input id=\"form_disabled_fieldset_descendant_legend_child\">\n      </legend>\n      <input name=\"form[disabled_fieldset_descendant]\" id=\"form_disabled_fieldset_descendant\"/>\n    </fieldset>\n  </fieldset>\n\n  <p>\n    <select data-test-id=\"my_test_id\">\n      <optgroup label=\"Level One\">\n       <option> A.1 </option>\n      </optgroup>\n      <optgroup label=\"Level Two\" disabled=\"disabled\">\n       <option> A.B.1 </option>\n      </optgroup>\n      <option> A.2 </option>\n    </select>\n  </p>\n\n  <p>\n    <input type=\"button\" aria-label=\"Aria button\" name=\"form[fresh]\" id=\"fresh_btn\" value=\"i am fresh\"/>\n    <input type=\"submit\" name=\"form[awesome]\" id=\"awe123\" data-test-id=\"test_id_button\" title=\"What an Awesome Button\" value=\"awesome\"/>\n    <input type=\"submit\" name=\"form[crappy]\" id=\"crap321\" value=\"crappy\"/>\n    <input type=\"image\" name=\"form[okay]\" id=\"okay556\" title=\"Okay 556 Image\" value=\"okay\" alt=\"oh hai thar\"/>\n    <button type=\"submit\" id=\"click_me_123\" title=\"Click Title button\" value=\"click_me\">Click me!</button>\n    <button type=\"submit\" name=\"form[no_value]\">No Value!</button>\n    <button id=\"no_type\">No Type!</button>\n    <button><img alt=\"A horse eating hay\"/></button>\n    <button id=\"button_with_label\"></button>\n    <label for=\"button_with_label\">button with label element</label>\n    <label>\n      button within label element\n      <button></button>\n    </label>\n    <label>\n      role=button within label element\n      <span role=\"button\">with other text</span>\n    </label>\n    <input type=\"button\" disabled=\"disabled\" value=\"Disabled button\"/>\n    <span role=\"button\">ARIA button</span>\n  </p>\n\n  <p>\n    <input type=\"date\" name=\"form[date]\" id=\"form_date\"/>\n    <input type=\"time\" name=\"form[time]\" id=\"form_time\"/>\n    <input type=\"datetime-local\" name=\"form[datetime]\" id=\"form_datetime\">\n  </p>\n\n  <p>\n    <input id=\"readonly\" name=\"form[readonly_test]\" readonly/>\n    <input id=\"not_readonly\" name=\"form[readonly_test]\" />\n  </p>\n\n  <p>\n    <input id=\"required\" name=\"form[required]\" required />\n    <input id=\"length\" name=\"form[length]\" minlength=\"4\" maxlength=\"4\" />\n  </p>\n</form>\n\n<input type=\"text\" name=\"form[outside_input]\" value=\"outside_input\" form=\"form1\"/>\n\n<label>\n  Nested Label\n  <input type=\"text\" name=\"nested_label\" id=\"nested_label\"/>\n</label>\n\n<label id=\"wrapper_label\">\n  Wrapper Label\n  <input type=\"checkbox\"/>\n</label>\n\n<form id=\"form1\" action=\"/form\" method=\"post\">\n  <input type=\"text\" name=\"form[which_form]\" value=\"form1\" id=\"form_which_form\"/>\n  <input type=\"text\" name=\"form[for_form2]\" value=\"for_form2\" form=\"form2\"/>\n  <input type=\"submit\" name=\"form[submit_form1]\" value=\"submit_form1\" id=\"submit_form1\"/>\n</form>\n\n<button type=\"submit\" name=\"form[outside_button]\" value=\"outside_button\" form=\"form2\">Outside!</button>\n\n<form id=\"form2\" action=\"/form\" method=\"post\">\n  <input type=\"text\" name=\"form[which_form]\" value=\"form2\" id=\"form_which_form2\"/>\n  <input type=\"submit\" name=\"form[unused]\" value=\"unused\"/>\n  <button type=\"submit\" name=\"form[other_form_button]\" value=\"other_form_button\" form=\"form1\">Form1</button>\n</form>\n\n<button type=\"submit\" name=\"form[no_form_button]\" value=\"no_form_button\">No Form</button>\n\n<textarea name=\"form[outside_textarea]\" form=\"form1\">Some text here</textarea>\n<select name=\"form[outside_select]\" form=\"form1\">\n  <option>Lisp</option>\n  <option selected=\"selected\">Ruby</option>\n  <option>Php</option>\n</select>\n\n<input type=\"submit\" name=\"form[outside_submit]\" value=\"outside_submit\" form=\"form1\"/>\n\n<form id=\"get-form\" action=\"/form/get?foo=bar\" method=\"get\">\n  <p>\n    <label for=\"form_middle_name\">Middle Name</label>\n    <input type=\"text\" name=\"form[middle_name]\" value=\"Darren\" id=\"form_middle_name\"/>\n  </p>\n\n  <p>\n    <input type=\"submit\" name=\"form[mediocre]\" id=\"mediocre\" value=\"med\" aria-label=\"Mediocre Button\"/>\n    <input type=\"submit\" formaction=\"/form/get?bar=foo\" id=\"mediocre2\" value=\"med2\"/>\n  <p>\n</form>\n\n<form action=\"/upload_empty\" method=\"post\" enctype=\"multipart/form-data\">\n  <p>\n    <label for=\"form_file_name\">File Name</label>\n    <input type=\"file\" name=\"form[file]\" id=\"form_file\"/>\n  </p>\n\n  <p>\n    <input type=\"hidden\" name=\"form[dummy]\" value=\"ensure params[:form] exists\"/>\n    <input type=\"submit\" value=\"Upload Empty\"/>\n  <p>\n</form>\n\n<form action=\"/upload_empty\" method=\"post\" enctype=\"multipart/form-data\">\n  <p>\n    <label>\n      <input type=\"file\" name=\"form[file]\" multiple=\"multiple\"/>\n      Multiple empty files\n    </label>\n  </p>\n\n  <p>\n    <input type=\"hidden\" name=\"form[dummy]\" value=\"ensure params[:form] exists\"/>\n    <input type=\"submit\" value=\"Upload Empty Multiple\"/>\n  <p>\n</form>\n\n<form action=\"/upload\" method=\"post\" enctype=\"multipart/form-data\">\n  <p>\n    <label for=\"form_file_name\">File Name</label>\n    <input type=\"file\" name=\"form[file_name]\" id=\"form_file_name\"/>\n  </p>\n\n  <p>\n    <label for=\"form_document\">Single Document</label>\n    <input type=\"file\" name=\"form[document]\" id=\"form_document\"/>\n  </p>\n\n  <p>\n    <input type=\"submit\" value=\"Upload Single\"/>\n  <p>\n</form>\n\n<form action=\"/form\" method=\"post\" enctype=\"multipart/form-data\">\n  <input type=\"hidden\" name=\"form[document2]\" value=\"hidden_field\"/>\n\n  <p>\n    <label for=\"form_document\">Document with hidden</label>\n    <input type=\"file\" name=\"form[document2]\" id=\"form_document2\"/>\n  </p>\n\n  <p>\n    <input type=\"submit\" value=\"Upload Empty With Hidden\"/>\n  <p>\n</form>\n\n<form action=\"/upload_multiple\" method=\"post\" enctype=\"multipart/form-data\">\n  <p>\n    <label for=\"form_multiple_file_name\">File Name</label>\n    <input type=\"file\" name=\"form[multiple_file_name]\" id=\"form_multiple_file_name\"/>\n  </p>\n\n  <p>\n    <label for=\"form_multiple_documents\">Multiple Documents</label>\n    <input type=\"file\" name=\"form[multiple_documents][]\" id=\"form_multiple_documents\" multiple=\"multiple\" />\n  </p>\n\n  <p>\n    <label for=\"form_directory_upload\">Directory Upload</label>\n    <input type=\"file\" name=\"form[multiple_documents][]\" id=\"form_directory_upload\" multiple=\"multiple\" webkitdirectory=\"webkitdirectory\" mozdirectory=\"mozdirectory\" />\n  </p>\n\n  <p>\n    <input type=\"submit\" value=\"Upload Multiple\"/>\n  <p>\n</form>\n\n<form action=\"/redirect\" method=\"post\">\n  <p>\n    <input type=\"submit\" value=\"Go FAR\"/>\n  </p>\n\n  <input type=\"hidden\" name=\"form[data]\" value=\"TWTW\"/>\n  <p>\n    <button formaction='/redirect_307'>Go 307</button>\n  </p>\n  <p>\n    <button formaction='/redirect_308'>Go 308</button>\n  </p>\n</form>\n\n<form action=\"/form\" method=\"post\">\n  <p>\n    <label for=\"html5_email\">Html5 Email</label>\n    <input type=\"email\" name=\"form[html5_email]\" value=\"person@email.com\" id=\"html5_email\"/>\n  </p>\n  <p>\n    <label for=\"html5_multiple_email\">Html5 Multiple Email</label>\n    <input type=\"email\" multiple name=\"form[html5_multiple_email]\" value=\"person@email.com\" id=\"html5_multiple_email\"/>\n  </p>\n  <p>\n    <label for=\"html5_url\">Html5 Url</label>\n    <input type=\"url\" name=\"form[html5_url]\" value=\"http://www.example.com\" id=\"html5_url\"/>\n  </p>\n  <p>\n    <label for=\"html5_search\">Html5 Search</label>\n    <input type=\"search\" name=\"form[html5_search]\" value=\"what are you looking for\" id=\"html5_search\"/>\n  </p>\n  <p id=\"emergency\">Emergency Number</p>\n  <p>\n    <label for=\"html5_tel\">Html5 Tel</label>\n    <input type=\"tel\" aria-labelledby=\"emergency\" name=\"form[html5_tel]\" value=\"911\" id=\"html5_tel\"/>\n  </p>\n  <p>\n    <label for=\"html5_color\">Html5 Color</label>\n    <input type=\"color\" name=\"form[html5_color]\" value=\"#FFFFFF\" id=\"html5_color\"/>\n  </p>\n\n  <p>\n    <input type=\"submit\" name=\"form[html5_submit]\" value=\"html5_submit\"/>\n  </p>\n</form>\n\n<form action=\"/form\" method=\"post\">\n  <p>\n    <button type=\"submit\" name=\"form[button]\" value=\"button_first\">Just an input that came first</button>\n    <button type=\"submit\" name=\"form[button]\" value=\"button_second\">Just an input</button>\n    <input type=\"submit\" name=\"form[button]\" value=\"Just a button that came first\"/>\n    <input type=\"submit\" name=\"form[button]\" value=\"Just a button\"/>\n  </p>\n</form>\n\n<form action=\"/other_form\" method=\"post\">\n  <p>\n    <input type=\"text\" name=\"form[which_form]\" value=\"formaction form\" aria-label=\"Unlabelled Input\"/>\n  </p>\n  <input type=\"submit\" name=\"form[button]\" formaction=\"/form\" value=\"Formaction button\"/>\n  <input type=\"submit\" name=\"form[button]\" formaction=\"/form/get\" formmethod=\"get\" value=\"Formmethod button\"/>\n</form>\n\n<form action=\"relative\" method=\"post\">\n  <p>\n    <input type=\"submit\" name=\"form[relative]\" value=\"Relative Action\" />\n  </p>\n</form>\n\n<form method=\"post\">\n  <p>\n    <input type=\"submit\" name=\"form[no_action]\" value=\"No Action\" />\n  </p>\n</form>\n\n<form id=\"single_input_form\" action=\"/form\" method=\"post\">\n  <input type=\"text\" name=\"form[single_input]\" id=\"single_input\"/>\n</form>\n\n<form id=\"two_input_form\" action=\"/form\" method=\"post\">\n  <input type=\"text\" name=\"form[two_input_1]\" id=\"two_input_1\"/>\n  <input type=\"text\" name=\"form[two_input_2]\" id=\"two_input_2\"/>\n</form>\n\n<label>Confusion\n  <input type=\"checkbox\" id=\"confusion_checkbox\" class=\"confusion-checkbox confusion\"/>\n</label>\n\n<label>Confusion\n  <input type=\"text\" id=\"confusion_text\" class=\"confusion-text confusion\"/>\n</label>\n\n<label>Confusion\n  <textarea id=\"confusion_textarea\" class=\"confusion confusion-textarea\"></textarea>\n</label>\n\n<p>\n  <label for=\"asterisk_input\">With Asterisk<abbr title=\"required\">*</abbr></label>\n  <input id=\"asterisk_input\" type=\"number\"value=\"2016\"/>\n</p>\n\n<p>\n  <input id=\"special\" {custom}=\"abcdef\" value=\"custom attribute\"/>\n</p>\n\n<p>\n  <div style=\"position: relative; overflow: hidden;\">\n    <button popovertarget=\"show\">Show popover</button>\n    <button popover id=\"show\">Should be clickable</button>\n  </div>\n</p>\n\n<label for=\"multi_label_checkbox\">\n  Label to click\n</label>\n<div>Something random that justifies the usage of a separate label</div>\n<label>\n  <div>\n    <input type=\"checkbox\" id=\"multi_label_checkbox\" style=\"display: none\"/>\n    <div>Visual representation of the checkbox</div>\n  </div>\n</label>\n"
  },
  {
    "path": "lib/capybara/spec/views/frame_child.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>This is the child frame title</title>\n        <script>\n        function closeWin() {\n          var iframe = window.parent.document.getElementById('childFrame');\n          iframe.parentNode.removeChild(iframe)\n        }\n        </script>\n    </head>\n    <body id=\"childBody\">\n      <a href=\"javascript:void(0)\" onClick=\"closeWin()\">Close Window Now</a>\n      <a href=\"javascript:void(0)\" onClick=\"setTimeout(function(){closeWin()}, 10)\">Close Window Soon</a>\n      <iframe src=\"/frame_one\" id=\"grandchildFrame1\"></iframe>\n      <iframe src=\"/frame_two\" id=\"grandchildFrame2\"></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/frame_one.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>This is the title of frame one</title>\n    </head>\n    <body>\n        <div id=\"divInFrameOne\">This is the text of divInFrameOne</div>\n        <div id=\"otherDivInFrameOne\">Some other text</div>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/frame_parent.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>This is the parent frame title</title>\n    </head>\n    <body id=\"parentBody\">\n      <iframe src='/frame_child' id='childFrame'></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/frame_two.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>This is the title of frame two</title>\n    </head>\n    <body>\n        <div id=\"divInFrameTwo\">This is the text of divInFrameTwo</div>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/header_links.erb",
    "content": "\n<p>\n  <a href=\"/get_header\">Link</a>\n</p>\n\n<form action=\"/get_header\" method=\"get\">\n  <p><input type=\"submit\" value=\"Post\"/></p>\n</form>\n"
  },
  {
    "path": "lib/capybara/spec/views/host_links.erb",
    "content": "\n<p>\n  <a href=\"/host\">Relative Host</a>\n  <a href=\"<%= params[:absolute_host] %>/host\">Absolute Host</a>\n</p>\n\n<form action=\"/host\">\n  <p><input type=\"submit\" value=\"Relative Host\"/></p>\n</form>\n\n<form action=\"<%= params[:absolute_host] %>/host\">\n  <p><input type=\"submit\" value=\"Absolute Host\"/></p>\n</form>\n"
  },
  {
    "path": "lib/capybara/spec/views/initial_alert.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <body>\n    <div>\n      Initial alert page\n    </div>\n    <script>\n      window.alert(\"Initial alert\");\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/layout.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n  </head>\n\n  <body>\n    <%= yield %>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/obscured.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>Obscured</title>\n    <style>\n      div {\n        width: 200px;\n        height: 200px;\n      }\n      #cover, #offscreen, #offscreen_wrapper {\n        position: absolute;\n      }\n      #obscured {\n        z-index: 1;\n        background-color: red;\n      }\n      #cover {\n        top: 0px;\n        z-index: 2;\n        background-color: blue;\n      }\n      #offscreen {\n        top: 2000px;\n        left: 2000px;\n        background-color: green;\n      }\n      #offscreen_wrapper {\n        top: 2000px;\n        left: 2000px;\n        overflow-x: scroll;\n        background-color: yellow;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"obscured\">\n      <input id=\"obscured_input\"/>\n    </div>\n    <div id=\"cover\"></div>\n    <iframe id=\"frameOne\" height=\"10px\" src=\"/frame_one\"></iframe>\n    <iframe id=\"nestedFrames\" src=\"/frame_parent\"></iframe>\n    <div id=\"offscreen_wrapper\">\n      <div id=\"offscreen\"></div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/offset.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>Offset</title>\n    <style>\n      body {\n        margin: 0px;\n      }\n      #wrapper {\n        width: 300px;\n        height: 300px;\n        margin: 0px;\n      }\n      #clicker {\n        position: relative;\n        width: 100px;\n        height: 100px;\n        top: 100px;\n        left: 100px;\n        background-color: red;\n        margin: 0px;\n      }\n    </style>\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"/offset.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  </head>\n  <body>\n    <div id=\"wrapper\">\n      <div id=\"clicker\"></div>\n    </div>\n  </body>\n  </html>\n"
  },
  {
    "path": "lib/capybara/spec/views/path.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <body>\n    <div>\n      <a href=\"#\">First Link</a>\n    </div>\n    Text node\n    <div>\n      <a href=\"#\">Second Link</a>\n      <a href=\"#\">Third Link</a>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/popup_one.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>Title of the first popup</title>\n    </head>\n    <body>\n        <div id=\"divInPopupOne\">This is the text of divInPopupOne</div>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/popup_two.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>Title of popup two</title>\n    </head>\n    <body>\n        <div id=\"divInPopupTwo\">This is the text of divInPopupTwo</div>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/postback.erb",
    "content": "\n<h1>Postback</h1>\n\n<form method=\"get\">\n  <p>\n    <input type=\"submit\" value=\"With no action\">\n  </p>\n</form>\n\n<form action=\"\" method=\"get\">\n  <p>\n    <input type=\"submit\" value=\"With blank action\">\n  </p>\n</form>\n"
  },
  {
    "path": "lib/capybara/spec/views/react.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <script src=\"https://unpkg.com/react@18/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script>\n      // https://codepen.io/gaearon/pen/VmmPgp?editors=0010\n      class NameForm extends React.Component {\n        constructor(props) {\n          super(props);\n          this.state = { value: '' };\n\n          this.handleChange = this.handleChange.bind(this);\n          this.handleSubmit = this.handleSubmit.bind(this);\n        }\n\n        handleChange(event) {\n          this.setState({ value: event.target.value });\n        }\n\n        handleSubmit(event) {\n          alert('A name was submitted: ' + this.state.value);\n          event.preventDefault();\n        }\n\n        render() {\n          return (\n            React.createElement(\"form\", { onSubmit: this.handleSubmit },\n            React.createElement(\"label\", null, \"Name:\",\n\n            React.createElement(\"input\", { type: \"text\", value: this.state.value, onChange: this.handleChange })),\n\n            React.createElement(\"input\", { type: \"submit\", value: \"Submit\" })));\n        }}\n\n\n        ReactDOM.render(\n        React.createElement(NameForm, null),\n        document.getElementById('root'));\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/scroll.erb",
    "content": "<!DOCTYPE html>\n<html style=\"height: 250%; width: 150%\">\n  <head>\n    <style>\n      * { padding: 0; }\n      div { position: absolute; }\n      #scroll { top: 125%; }\n      #scrollable { top: 150%; overflow-y: scroll; overflow-x: scroll; height: 50px; width: 50px; position: relative; border: 1px solid black;}\n      #inner { top: 50%; }\n    </style>\n  </head>\n  <body style=\"height: 100%; width: 100%\">\n    <div id=\"scroll\" style = \"top: 125%\">scroll</div>\n    <div id=\"scrollable\">\n      <div style=\"height: 200px; width: 200px; poistion: relative\">\n        <div id=\"inner\">inner</div>\n      </div>\n    </div>\n  </div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/spatial.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>spatial</title>\n    <style>\n      #spatial {\n        display: grid;\n        grid-template-columns: repeat(3, 1fr);\n        grid-gap: 10px;\n        grid-auto-rows: minmax(100px, auto);\n      }\n      .footer {\n        grid-column: 1 / 4;\n      }\n    </style>\n  </head>\n\n  <body id=\"spatial\">\n    <div class=\"corner\">1</div>\n    <div class=\"distance\">2</div>\n    <div class=\"corner\">3</div>\n    <div>4</div>\n    <div class=\"center\">5</div>\n    <div>6</div>\n    <div class=\"corner\">7</div>\n    <div>8</div>\n    <div class=\"corner\">9</div>\n    <div class=\"footer distance\">10</div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/tables.erb",
    "content": "\n<form action=\"/form\" method=\"post\">\n  <table id=\"agent_table\">\n    <caption>Agent</caption>\n\n    <tr onclick=\"this.querySelector('td label').innerHTML = 'Clicked'\">\n      <td>\n        <label for=\"form_agent_name\">Name</label>\n      </td>\n      <td>\n        <input type=\"text\" name=\"form[agent_name]\" value=\"James\" id=\"form_agent_name\"/>\n      </td>\n    </tr>\n\n    <tr>\n      <td colspan=\"2\">\n        <input type=\"submit\" value=\"Create\"/>\n      </td>\n    </tr>\n  </table>\n</form>\n\n<form action=\"/form\" method=\"post\">\n  <table id=\"girl_table\">\n    <caption>Girl</caption>\n\n    <tr>\n      <td>\n        <label for=\"form_girl_name\">Name</label>\n      </td>\n      <td>\n        <input type=\"text\" name=\"form[girl_name]\" value=\"Vesper\" id=\"form_girl_name\"/>\n      </td>\n    </tr>\n\n    <tr>\n      <td colspan=\"2\">\n        <input type=\"submit\" value=\"Create\"/>\n      </td>\n    </tr>\n  </table>\n</form>\n\n<form action=\"/form\" method=\"post\">\n  <table id=\"villain_table\">\n    <caption>Villain</caption>\n\n    <tr>\n      <td>\n        <label for=\"form_villain_name\">Name</label>\n      </td>\n      <td>\n        <input type=\"text\" name=\"form[villain_name]\" value=\"Ernst\" id=\"form_villain_name\"/>\n      </td>\n    </tr>\n\n    <tr>\n      <td colspan=\"2\">\n        <input type=\"submit\" value=\"Create\"/>\n      </td>\n    </tr>\n  </table>\n</form>\n\n<table>\n  <caption>Horizontal Headers</caption>\n  <thead>\n    <tr>\n      <th>First Name</th>\n      <th>Last Name</th>\n      <th>City</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>Thomas</td>\n      <td>Walpole</td>\n      <td>Oceanside</td>\n    </tr>\n    <tr>\n     <td>Danilo</td>\n     <td>Wilkinson</td>\n     <td>Johnsonville</td>\n    </tr>\n    <tr>\n      <td>Vern</td>\n      <td>Konopelski</td>\n      <td>Everette</td>\n    </tr>\n    <tr>\n      <td>Ratke</td>\n      <td>Lawrence</td>\n      <td>East Sorayashire</td>\n    </tr>\n    <tr>\n      <td>Palmer</td>\n      <td>Sawayn</td>\n      <td>West Trinidad</td>\n    </tr>\n  </tbody>\n</table>\n\n<table>\n  <caption>Vertical Headers</caption>\n  <tr>\n    <th>First Name</th>\n    <td>Thomas</td>\n    <td>Danilo</td>\n    <td>Vern</td>\n    <td>Ratke</td>\n    <td>Palmer</td>\n  </tr>\n  <tr>\n    <th>Last Name</th>\n    <td>Walpole</td>\n    <td>Wilkinson</td>\n    <td>Konopelski</td>\n    <td>Lawrence</td>\n    <td>Sawayn</td>\n  </tr>\n  <tr>\n    <th>City</th>\n    <td>Oceanside</td>\n    <td>Johnsonville</td>\n    <td>Everette</td>\n    <td>East Sorayashire</td>\n    <td>West Trinidad</td>\n  </tr>\n</table>\n\n"
  },
  {
    "path": "lib/capybara/spec/views/with_animation.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_animation</title>\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"/jquery-ui.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"/test.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script type=\"text/javascript\">\n      $(document).on('transitionend', function(){\n        $(document.body).append('<div>Transition Ended</div>')\n      });\n      $(document).on('animationend', function(){\n        $(document.body).append('<div>Animation Ended</div>')\n      });\n      $(document).on('contextmenu', function(e){\n        e.preventDefault();\n      });\n    </script>\n    <style>\n      html {\n        scroll-behavior: smooth;\n      }\n\n      body {\n        min-height: 2000px;\n      }\n\n      .transition.away {\n          width: 0%;\n      }\n\n      a {\n          display: inline-block;\n          width: 100%;\n          overflow: hidden;\n      }\n\n      a::after {\n        content: \"\";\n        width: 0px;\n        height: 0px;\n        background-color: blue;\n      }\n\n      a:not(.away) {\n        height: 20px;\n      }\n\n      a.transition {\n        transition: all 3s ease-in-out;\n      }\n\n      @keyframes animation {\n          0%   {height: 20px; width: 100%;}\n          100% {height: 0px; width: 0%;}\n      }\n\n      a.animation.away {\n        animation-name: animation;\n        animation-duration: 3s;\n        animation-fill-mode: forwards;\n      }\n\n      @keyframes pseudo_grow {\n        100% { height: 100px, width: 100px };\n      }\n\n      a.animation.pseudo::after {\n        animation: pseudo_grow 3s forwards;\n      }\n    </style>\n  </head>\n\n  <body id=\"with_animation\">\n    <a href='#' class='transition' onclick='this.classList.add(\"away\")'>transition me away</a>\n    <a href='#' class='animation' onclick='this.classList.add(\"away\")' oncontextmenu='this.classList.add(\"pseudo\")'>\n      animate me away\n    </a>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_base_tag.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <base href=\"http://example2.com\" />\n    <title>with_external_source</title>\n  </head>\n  <body id=\"with_js\">\n    <h1>FooBar</h1>\n  </body>\n</html\n"
  },
  {
    "path": "lib/capybara/spec/views/with_count.erb",
    "content": "\n<h1>This page is used for testing number options of has_text?</h1>\n\n<p>count1</p>\n<div>\n  <p>2 count</p>\n  <p>Count</p>\n</div>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_dragula.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_dragula</title>\n\n  </head>\n\n  <body id=\"with_dragula\">\n    <div id=\"sortable\">\n      <div class=\"item1\">Item 1</div>\n      <div class=\"item2\">Item 2</div>\n      <div class=\"item3\">Item 3</div>\n      <div class=\"item4\">Item 4</div>\n      <div class=\"item5\">Item 5</div>\n    </div>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.js\" type=\"text/javascript\"></script>\n    <script>\n      let container = document.getElementById(\"sortable\");\n      dragula([container]);\n      container.className = \"ready\"\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_fixed_header_footer.erb",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    header { height: 45px; position: fixed; top: 0; background-color: red; width: 100%;}\n    footer { height: 45px; position: fixed; bottom: 0; background-color: red; width: 100%;}\n    #main { margin: 45px;}\n    #tall { display: block; height: 2000px;}\n  </style>\n</head>\n<body>\n  <header>My headers</header>\n    <div id=\"main\">\n      <div id=\"tall\">A tall block</div>\n      <a href=\"/\">Go to root</a>\n    </div>\n  <footer>My footer</footer>\n</body>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_hover.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_hover</title>\n  </head>\n\n  <body id=\"with_hover\">\n    <style type=\"text/css\">\n      .hidden_until_hover {display: none;}\n      .wrapper:hover .hidden_until_hover { display: block }\n    </style>\n    <a href='with_hover1'>Other hover page</a>\n    <div class=\"wrapper\">\n      Some text here so the wrapper has size\n      <div class=\"hidden_until_hover\">Here I am</div>\n    </div>\n    <div style=\"display: block; height: 1000px; width: 100%\"></div>\n    <div class=\"wrapper scroll_needed\" >\n      Some text here so the wrapper has size\n      <div class=\"hidden_until_hover\">Here I am</div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_hover1.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n  </head>\n\n  <body>\n    <a href=\"with_hover\">Go back</a>\n  </body>\n</html>"
  },
  {
    "path": "lib/capybara/spec/views/with_html.erb",
    "content": "\n<style>\n  p { display: block; }\n</style>\n\n<div id=\"referrer\"><%= referrer %></div>\n<h1>This is a test</h1>\n\n<h2 class=\"no text\"></h2>\n<h2 class=\"no text\"></h2>\n<h2 class=\"head\" id=\"h2one\">Header Class Test One</h2>\n<h2 class=\"head\" id=\"h2two\">Header Class Test Two</h2>\n<h2 class=\"head\" id=\"h2_\">Header Class Test Three</h2>\n<h2 class=\"head\">Header Class Test Four</h2>\n<h2 class=\"head\">Header Class <span style=\"display: none\">Random</span>Test Five</h2>\n\n<span class=\"number\">42</span>\n<span>Other span</span>\n\n<p class=\"para\" id=\"first\" data-random=\"abc\\def\" style=\"line-height: 25px;\">\n  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n  tempor incididunt ut <a href=\"/with_simple_html\" title=\"awesome title\" class=\"simple\" tabindex=\"1\" target=\"_self\">labore</a>\n  et dolore magna aliqua. Ut enim ad minim veniam,\n  quis nostrud exercitation <a href=\"/foo\" id=\"foo\" data-test-id=\"test-foo\">ullamco</a> laboris nisi\n  ut aliquip ex ea commodo consequat.\n  <a href=\"/with_simple_html\" aria-label=\"Go to simple\" data-test-id=\"test-simple\"><img id=\"first_image\" width=\"20\" height=\"20\" alt=\"awesome image\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=\"/></a>\n</p>\n\n<p class=\"para\" id=\"second\" style=\"display: inline;\">\n  Duis aute irure dolor in reprehenderit in voluptate velit esse cillum\n  dolore eu fugiat <a href=\"/redirect\" id=\"red\">Redirect</a> pariatur. Excepteur sint occaecat cupidatat non proident,\n  sunt in culpa qui officia\n  text   with &nbsp;\n  whitespace\n  id est laborum.\n</p>\n\n<p>\n  <input type=\"text\" id=\"test_field\" spellcheck=\"TRUE\" data-test-id=\"test_id\" value=\"monkey\"/>\n  <input type=\"text\" readonly=\"readonly\" spellcheck=\"FALSE\" value=\"should not change\" />\n  <textarea id=\"normal\" data-other-test-id=\"test_id\">\nbanana</textarea>\n  <textarea id=\"additional_newline\">\n\nbanana</textarea>\n  <textarea readonly=\"readonly\">textarea should not change</textarea>\n  <a href=\"/redirect_back\">BackToMyself</a>\n  <a title=\"twas a fine link\" href=\"/redirect\">A link came first</a>\n  <a title=\"a fine link\" href=\"/with_simple_html\">A link</a>\n  <a title=\"a fine link with data method\" data-method=\"delete\" href=\"/delete\">A link with data-method</a>\n  <a title=\"a fine link with capitalized data method\" data-method=\"DELETE\" href=\"/delete\">A link with capitalized data-method</a>\n  <a>No Href</a>\n  <a href=\"\">Blank Href</a>\n  <a href=\"#\">Blank Anchor</a>\n  <a href=\"javascript:void(0)\">Blank JS Anchor</a>\n  <a href=\"#anchor\">Normal Anchor</a>\n  <a href=\"/with_simple_html#anchor\">Anchor on different page</a>\n  <a href=\"/with_html#anchor\">Anchor on same page</a>\n  <a href=\"with_html\">Relative</a>\n  <a href=\"//<%= request.host_with_port %>/foo\">Protocol</a>\n  <input type=\"text\" checked=\"checked\" id=\"checked_field\">\n  <a href=\"/redirect\"><img width=\"20\" height=\"20\" alt=\"very fine image\" /></a>\n  <a href=\"/with_simple_html\"><img width=\"20\" height=\"20\" alt=\"fine image\" /></a>\n  <a href=\"/with_simple_html\" disabled=\"disabled\">Disabled link</a>\n\n  <a href=\"?query_string=true\">Naked Query String</a>\n  <% if params[:query_string] %>\n    <em>Query String sent</em>\n  <% end %>\n</p>\n\n<div id=\"hidden\" style=\"display: none;\">\n  <div id=\"hidden_via_ancestor\">Inside element with hidden ancestor</div>\n  <a href=\"/with_simple_html\" title=\"hidden link\" class=\"simple\">hidden link</a>\n</div>\n\n<div id=\"hidden_attr\" hidden=\"hidden\">\n  <a id=\"hidden_attr_via_ancestor\">hidden attribute ancestor link</a>\n</div>\n\n\n<div id=\"hidden-text\">\n  Some of this text is <em style=\"display:none\">hidden!</em>\n</div>\n\n<div id=\"some-hidden-text\">\n  Some of this text is not hidden <em style=\"display:none\">and some is hidden</em>\n</div>\n\n<div style=\"display: none;\">\n  <a id=\"first_invisible\" class=\"hidden\">first hidden link</a>\n</div>\n\n<div style=\"display: none;\">\n  <a id=\"invisible\" class=\"visibility hidden\">hidden link</a>\n</div>\n\n<div>\n  <a id=\"visible\" class=\"visibility\">visible link</a>\n</div>\n\n<div>\n  Number 42\n</div>\n\n<ul>\n  <li class=\"beatle guitarist\" id=\"john\">John</li>\n  <li class=\"beatle bassist drummer\" id=\"paul\">Paul</li>\n  <li class=\"beatle guitarist\" id=\"george\">George</li>\n  <li class=\"beatle drummer\" id=\"ringo\">Ringo</li>\n</ul>\n\n<div>\n  <div class=\"singular\">singular</div>\n  <div class=\"multiple\">multiple one</div>\n  <div class=\"multiple\">multiple two</div>\n  <div class=\"almost_singular but_not_quite\">almost singular but not quite</div>\n  <div class=\"almost_singular\">almost singular</div>\n</div>\n\n<input type=\"text\" disabled=\"disabled\" name=\"disabled_text\" value=\"This is disabled\"/>\n<input type=\"hidden\" id=\"hidden_input\" name=\"hidden_input\" value=\"This is a hidden input\"/>\n\n<div>\n  <a id=\"link_placeholder\">No href</a>\n  <a id=\"link_blank_href\" href=\"\">Blank href</a>\n</div>\n\n<div id=\"uppercase\" style=\"text-transform: uppercase;\">\n  text here\n</div>\n\n<div id=\"ancestor3\">\n  Ancestor\n  <div id=\"ancestor2\">\n    Ancestor\n    <div id=\"ancestor1\">\n      Ancestor\n      <div id=\"child\">Child</div>\n    </div>\n    <div id=\"ancestor1_sibling\">\n      ASibling\n    </div>\n  </div>\n  <button id=\"ancestor_button\" type=\"submit\" disabled>\n    <img id=\"button_img\" width=\"20\" height=\"20\" alt=\"button img\"/>\n  </button>\n</div>\n\n<div id=\"sibling_test\">\n  <div id=\"sibling_wrapper\" data-pre=true>\n    <div id=\"pre_sibling\" data-pre=true>Pre Sibling</div>\n    <div id=\"mid_sibling\">Mid Sibling</div>\n    <div id=\"post_sibling\" data-post=true>Post Sibling</div>\n  </div>\n  <div id=\"other_sibling_wrapper\" data-post=true>\n    <div data-pre=true>Pre Sibling</div>\n    <div data-post=true>Post Sibling</div>\n  </div>\n</div>\n\n<div id='1escape.me' class=\"2escape\">needs escaping</div>\n\n<div id=\"normalized\">\n  Some text<div>More   text</div>\n  <div> And more text</div>\n  Even more &nbsp;&nbsp; text\n\n  on multiple lines\n</div>\n\n<div id=\"non_visible_normalized\" style=\"display: none\">\n  Some text<div>More   text</div>\n  <div> And more text</div>\n  Even more &nbsp;&nbsp; text\n\n  on multiple lines\n</div>\n\n<div id=\"ws\">\n&#x20;&#x1680;&#x2000;&#x2001;&#x2002; &#x2003;&#x2004;&nbsp;&#x2005; &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x202F;&#x205F;&#x3000;\n</div>\n\n<details id=\"closed_details\">\n  <summary>\n    <h6>Something</h6>\n  </summary>\n  <ul>\n    <li>Random</li>\n    <li>Things</li>\n  </ul>\n</details>\n\n<details id=\"open_details\" open>\n  <summary>\n    <h6>Summary</h6>\n  </summary>\n  <div>\n    Contents\n  </div>\n</details>\n\n<div>\n  <div style=\"position: relative; overflow: hidden;\">\n    <button popovertarget=\"show\">Show popover</button>\n    <button popover id=\"not_shown\">Should not be clickable</button>\n    <button popover id=\"show\">Should be clickable</button>\n  </div>\n</div>\n\n<div>\n  <div style=\"position: relative; overflow: hidden;\">\n    <button popovertarget=\"popover_parent\">Show parent popover</button>\n    <div popover id=\"popover_parent\">\n      <div id=\"popover_child\">\n        Popover Contents\n      </div>\n    </div>\n  </div>\n</div>\n\n\n<div style='height: 1000px'>spacer</div>\n\n<template id=\"template\">\n  <input />\n</template>\n\n<a href=\"/download.csv\" download>Download Me</a>\n<a href=\"/download.csv\" download=\"other.csv\">Download Other</a>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_html5_svg.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Namespace</title>\n  </head>\n  <body id=\"body\">\n    <div>\n      <svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid slice\"\n           style=\"width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;\">\n        <linearGradient id=\"gradient\">\n          <stop class=\"begin\" offset=\"0%\"/>\n          <stop class=\"end\" offset=\"100%\"/>\n        </linearGradient>\n        <rect x=\"0\" y=\"0\" width=\"100\" height=\"100\" style=\"fill:url(#gradient)\" />\n        <rect x=\"150\" y=\"150\" width=\"25\" height=\"25\" style=\"fill:url(#gradient)\" />\n        <circle cx=\"50\" cy=\"50\" r=\"30\" style=\"fill:url(#gradient)\" />\n      </svg>\n    <div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_html_entities.erb",
    "content": "\nEncoding with &mdash; html entities &raquo;\n"
  },
  {
    "path": "lib/capybara/spec/views/with_jquery_animation.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_jquery_animation</title>\n    <style>\n      body {\n        height: 2000px;\n      }\n    </style>\n  </head>\n\n  <body id=\"with_animation\">\n    <a href=\"#\" id='scroll'>scroll top 500</a>\n\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script type='text/javascript'>\n      $('#scroll').click(function(e){\n        e.preventDefault();\n        $('html, body').animate({ scrollTop: 500 }, 'slow');\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_js.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_js</title>\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"/jquery-ui.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"/test.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  </head>\n\n  <body id=\"with_js\">\n    <h1>FooBar</h1>\n\n    <p id=\"change\">This is text</p>\n    <a id=\"drag_link\" href='#'>This link is non-HTML5 draggable</a>\n    <div id=\"drag\">\n      <p>This is a draggable element.</p>\n    </div>\n    <div id=\"drop\">\n      <p>It should be dropped here.</p>\n    </div>\n    <div id=\"drop_scroll\">\n      <p>It should be dropped here.</p>\n    </div>\n    <div id=\"drop_html5_scroll\" class=\"drop\">\n      <p>It should be dropped here.</p>\n    </div>\n    <div id=\"drag_html5\" draggable=\"true\">\n      <p>This is an HTML5 draggable element.</p>\n    </div>\n    <a id=\"drag_link_html5\" href=\"#\"><p>This is an HTML5 draggable link</p></a>\n    <div id=\"drop_html5\" class=\"drop\">\n      <p>It should be dropped here.</p>\n    </div>\n\n    <p><a href=\"#\" id=\"clickable\">Click me</a></p>\n    <p><a href=\"#\" id=\"slow-click\">Slowly</a></p>\n    <p><span id=\"aria-button\" role=\"button\">ARIA button</span></p>\n    <p><span role=\"button\">ARIA button2</span></p>\n\n    <p>\n      <select id=\"waiter\">\n        <option>Foo</option>\n        <option>My Waiting Option</option>\n      </select>\n    </p>\n\n    <p>\n      <input type=\"text\" name=\"with_focus_event\" value=\"\" id=\"with_focus_event\"/>\n    </p>\n\n    <p>\n      <input type=\"text\" name=\"with_change_event\" value=\"default value\" id=\"with_change_event\"/>\n    </p>\n\n    <p>\n      <div contenteditable='true' id='existing_content_editable'>Editable content</div>\n      <div contenteditable='true' id='blank_content_editable' style='height: 1em;'></div>\n      <div contenteditable='true' id='existing_content_editable_child_parent' style='height: 1em;'>\n        Some content\n        <div id='existing_content_editable_child' style='height: 1em;'>Content</div>\n      </div>\n    </p>\n\n    <p>\n      <input type=\"checkbox\" id=\"checkbox_with_event\"/>\n    </p>\n\n    <p>\n      <input type=\"submit\" id=\"fire_ajax_request\" value=\"Fire Ajax Request\"/>\n    </p>\n\n    <p>\n      <a id=\"reload-link\" href=\"#\">Reload!</a>\n      <em>this won't change</em>\n      <div id=\"reload-me\"><em>waiting to be reloaded</em></div>\n    </p>\n\n    <p>\n      <a id=\"reload-list\" href=\"#\">Fetch new list!</a>\n      <ul id=\"the-list\">\n        <li>Item 1</li>\n        <li>Item 2</li>\n      </ul>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"change-title\">Change title</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"change-size\">Change size</a>\n    </p>\n\n    <p id=\"click-test\">Click me</p>\n\n    <p>\n      <a href=\"#\" id=\"open-alert\">Open alert</a>\n      <a href=\"/with_html\" id=\"alert-page-change\">Alert page change</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"open-delayed-alert\">Open delayed alert</a>\n      <a href=\"#\" id=\"open-slow-alert\">Open slow alert</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"open-confirm\">Open confirm</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"open-twice\">Open check twice</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"open-prompt\">Open prompt</a>\n    </p>\n\n    <p>\n      <a href=\"#\" id=\"open-prompt-with-default\">Open defaulted prompt</a>\n    </p>\n\n    <p>\n      <input id=\"disable-on-click\"/>\n    </p>\n    <p>\n      <input id=\"set-storage\"/>\n    </p>\n    <p>\n      <a href=\"#\" id=\"delayed-page-change\">Change page</a>\n      <a href=\"/with_html?options[]=things\">Non-escaped query options</a>\n      <a href=\"/with_html?options%5B%5D=things\">Escaped query options</a>\n    </p>\n\n    <p>\n      <input type=\"test\" name=\"with-key-events\" id=\"with-key-events\">\n      <p id=\"key-events-output\"></p>\n    </p>\n\n    <p>\n      <input type=\"file\" id=\"hidden_file\" style=\"opacity:0; display: none;\">\n      <label for=\"hidden_file\">Label for hidden file input</label>\n    </p>\n\n    <p>\n      <input type=\"file\" id=\"multiple-file\" multiple=\"multiple\"/>\n    </p>\n\n    <div id=\"drag_scroll\">\n      <p>This is a draggable element.</p>\n    </div>\n    <div id=\"drag_html5_scroll\" draggable=\"true\">\n      <p>This is an HTML5 draggable element.</p>\n    </div>\n\n    <div id=\"shadow\"></div>\n    <script type=\"text/javascript\">\n      // a javascript comment\n      var aVar = 123;\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_jstree.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_jstree</title>\n  </head>\n  <body id=\"with_jstree\">\n    <div id=\"container\">\n      <ul>\n        <li>Child node A</li>\n        <li>Child node B</li>\n        <li>Child node C</li>\n      </ul>\n    </div>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.8/jstree.min.js\"></script>\n    <script>\n      $(function () {\n        $('#container').jstree({\n          \"core\" : { \"check_callback\" : true }, // so that operations work\n          \"plugins\" : [\"dnd\"]\n        });\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_namespace.erb",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n    <title>Namespace</title>\n  </head>\n  <body id=\"body\">\n    <div>\n      <svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"\n        viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid slice\"\n        style=\"width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;\">\n        <linearGradient id=\"gradient\">\n          <stop class=\"begin\" offset=\"0%\"/>\n          <stop class=\"end\" offset=\"100%\"/>\n        </linearGradient>\n        <rect x=\"0\" y=\"0\" width=\"100\" height=\"100\" style=\"fill:url(#gradient)\" />\n        <rect x=\"150\" y=\"150\" width=\"25\" height=\"25\" style=\"fill:url(#gradient)\" />\n        <circle cx=\"50\" cy=\"50\" r=\"30\" style=\"fill:url(#gradient)\" />\n      </svg>\n    <div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_scope.erb",
    "content": "\n<h1>This page is used for testing various scopes</h1>\n\n<p id=\"for_foo\">\n  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor\n  incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia.\n  <a href=\"/redirect\">Go</a>\n  <input name=\"disabled\" disabled=\"disabled\"/>\n</p>\n\n<div id=\"for_bar\">\n  <ul>\n    <li>With Simple HTML: <a href=\"/with_simple_html\">Go</a>\n      <form action=\"/redirect\" method=\"post\" accept-charset=\"utf-8\">\n        <p>\n          <label for=\"simple_first_name\">First Name</label>\n          <input type=\"text\" name=\"first_name\" value=\"John\" id=\"simple_first_name\"/>\n        </p>\n        <p><input type=\"submit\" value=\"Go\"/></p>\n      </form>\n    </li>\n    <li>Bar: <a href=\"/foo\">Go</a>\n      <form action=\"/form\" method=\"post\" accept-charset=\"utf-8\">\n        <p>\n          <label for=\"bar_first_name\">First Name</label>\n          <input type=\"text\" name=\"form[first_name]\" value=\"Peter\" id=\"bar_first_name\"/>\n        </p>\n        <p>\n          <label for=\"bar_other_name\">Other Name</label>\n          <input type=\"text\" name=\"form[other_name]\" value=\"James\" id=\"bar_other_name\" disabled=\"disabled\"/>\n        </p>\n        <p><input type=\"submit\" value=\"Go\"/></p>\n      </form>\n    </li>\n  </ul>\n</div>\n\n<div id=\"another_foo\" onclick=\"this.innerHTML = 'I was clicked';\">\n  <ul>\n    <li>With Simple HTML: <a href=\"/\">Go</a></li>\n  </ul>\n</div>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_scope_other.erb",
    "content": "\n<h1>This page is used for testing various scopes</h1>\n\n<p id=\"for_foo\">\n  Different text same wrapper id\n</p>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_shadow.erb",
    "content": "<!DOCTYPE html>\n<%# Borrowed from Titus Fortner %>\n<html>\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Shadow DOM</title>\n  </head>\n  <body>\n    <div id=\"no_host\"></div>\n    <div id=\"shadow_host\"></div>\n    <a href=\"scroll.html\">scroll.html</a>\n    <script>\n      let shadowRoot = document.getElementById('shadow_host').attachShadow({mode: 'open'});\n      shadowRoot.innerHTML = `\n              <span class=\"wrapper\" id=\"shadow_content\"><span class=\"info\">some text</span></span>\n              <div id=\"nested_shadow_host\"></div>\n              <a href=\"scroll.html\">scroll.html</a>\n\t  \t\t  <div id=\"controls_wrapper\">\n                <input type=\"text\" />\n                <input type=\"checkbox\" id=\"shadow_checkbox\" />\n                <input type=\"file\" />\n\t \t\t  </div>\n            `;\n\n      let nestedShadowRoot = shadowRoot.getElementById('nested_shadow_host').attachShadow({mode: 'open'});\n      nestedShadowRoot.innerHTML = `\n              <div id=\"nested_shadow_content\"><div>nested text</div></div>\n            `;\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_simple_html.erb",
    "content": "\nBar\n"
  },
  {
    "path": "lib/capybara/spec/views/with_slow_unload.erb",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <script>\n    function delay_unload() {\n      var start = new Date();\n      var i = 0;\n      while ((new Date()) - start < 1000){ i = i + 1; };\n      return null;\n    }\n    window.onbeforeunload = delay_unload;\n    window.onunload = delay_unload;\n  </script>\n</head>\n<body>\n  <div>This delays unload by 2 seconds</div>\n</body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_sortable_js.erb",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"/>\n    <title>with_sortable_js</title>\n    <script src=\"https://cdn.jsdelivr.net/npm/sortablejs@1.12.0/dist/sortable.umd.min.js\" type=\"text/javascript\"></script>\n  </head>\n\n  <body id=\"with_sortable_js\">\n    <div id=\"sortable\">\n      <div class=\"item1\">Item 1</div>\n      <div class=\"item2\">Item 2</div>\n      <div class=\"item3\">Item 3</div>\n      <div class=\"item4\">Item 4</div>\n      <div class=\"item5\">Item 5</div>\n    </div>\n    <script>\n      new Sortable(document.getElementById(\"sortable\"));\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_unload_alert.erb",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <script>\n      window.onbeforeunload = function(e) {\n        return 'Unload?';\n      };\n  </script>\n</head>\n<body>\n  <div>This triggers an alert on unload</div>\n\n  <a href=\"/\">Go away</a>\n</body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/with_windows.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>With Windows</title>\n    <script src=\"/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script language=\"javascript\" type=\"text/javascript\">\n    $(document).ready(function(){\n      $('#openWindow').click(function(){\n        window.open('/popup_one', 'firstPopup');\n        return false;\n      });\n\n      $('#openWindowWithTimeout').click(function(){\n        setTimeout(function(){\n          window.open('/popup_one', 'timeoutPopup');\n        }, 600);\n        return false;\n      });\n\n      $('#openWindowWithLongerTimeout').click(function(){\n        setTimeout(function(){\n          window.open('/popup_one', 'longerTimeoutPopup');\n        }, 1400);\n        return false;\n      });\n\n      $('#openTwoWindows').click(function() {\n        window.open('/popup_one', 'firstPopup');\n        window.open('/popup_two', 'secondPopup');\n        return false;\n      });\n\n      $('body').addClass('loaded');\n    });\n    </script>\n  </head>\n  <body>\n    <button id=\"openWindow\">Open new window</button>\n\n    <button id=\"openWindowWithTimeout\">Open new window with timeout</button>\n\n    <button id=\"openWindowWithLongerTimeout\">Open new window with longer timeout</button>\n\n    <button id=\"openTwoWindows\">Open two windows</button>\n\n    <button id=\"doesNotOpenWindows\">Does not open windows</button>\n\n    <iframe src=\"/frame_one\" id=\"frameOne\"></iframe>\n\n    <div id=\"scope\">\n      <span>My scoped content</span>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/spec/views/within_frames.erb",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>With Frames</title>\n    </head>\n    <body>\n        <div id=\"divInMainWindow\">\n          This is the text for divInMainWindow\n          <iframe src=\"/frame_parent\" id=\"innerParentFrame\"></iframe>\n        </div>\n    <iframe src=\"/frame_one\" id=\"frameOne\" name=\"my frame one\"></iframe>\n    <iframe src=\"/frame_two\" id=\"frameTwo\"></iframe>\n    <iframe src=\"/frame_parent\" id=\"parentFrame\"></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "lib/capybara/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  VERSION = '3.40.0'\nend\n"
  },
  {
    "path": "lib/capybara/window.rb",
    "content": "# frozen_string_literal: true\n\nmodule Capybara\n  ##\n  # The {Window} class represents a browser window.\n  #\n  # You can get an instance of the class by calling any of:\n  #\n  # * {Capybara::Session#windows}\n  # * {Capybara::Session#current_window}\n  # * {Capybara::Session#window_opened_by}\n  # * {Capybara::Session#switch_to_window}\n  #\n  # Note that some drivers (e.g. Selenium) support getting size of/resizing/closing only\n  # current window. So if you invoke such method for:\n  #\n  # * window that is current, Capybara will make 2 Selenium method invocations\n  #   (get handle of current window + get size/resize/close).\n  # * window that is not current, Capybara will make 4 Selenium method invocations\n  #   (get handle of current window + switch to given handle + get size/resize/close + switch to original handle)\n  #\n  class Window\n    # @return [String]   a string that uniquely identifies window within session\n    attr_reader :handle\n\n    # @return [Capybara::Session] session that this window belongs to\n    attr_reader :session\n\n    # @api private\n    def initialize(session, handle)\n      @session = session\n      @driver = session.driver\n      @handle = handle\n    end\n\n    ##\n    # @return [Boolean] whether the window is not closed\n    def exists?\n      @driver.window_handles.include?(@handle)\n    end\n\n    ##\n    # @return [Boolean] whether the window is closed\n    def closed?\n      !exists?\n    end\n\n    ##\n    # @return [Boolean] whether this window is the window in which commands are being executed\n    def current?\n      @driver.current_window_handle == @handle\n    rescue @driver.no_such_window_error\n      false\n    end\n\n    ##\n    # Close window.\n    #\n    # If this method was called for window that is current, then after calling this method\n    # future invocations of other Capybara methods should raise\n    # {Capybara::Driver::Base#no_such_window_error session.driver.no_such_window_error} until another window will be switched to.\n    #\n    # @!macro about_current\n    #   If this method was called for window that is not current, then after calling this method\n    #   current window should remain the same as it was before calling this method.\n    #\n    def close\n      @driver.close_window(handle)\n    end\n\n    ##\n    # Get window size.\n    #\n    # @macro about_current\n    # @return [Array<(Integer, Integer)>] an array with width and height\n    #\n    def size\n      @driver.window_size(handle)\n    end\n\n    ##\n    # Resize window.\n    #\n    # @macro about_current\n    # @param width [Integer]  the new window width in pixels\n    # @param height [Integer]  the new window height in pixels\n    #\n    def resize_to(width, height)\n      wait_for_stable_size { @driver.resize_window_to(handle, width, height) }\n    end\n\n    ##\n    # Maximize window.\n    #\n    # If a particular driver (e.g. headless driver) doesn't have concept of maximizing it\n    # may not support this method.\n    #\n    # @macro about_current\n    #\n    def maximize\n      wait_for_stable_size { @driver.maximize_window(handle) }\n    end\n\n    ##\n    # Fullscreen window.\n    #\n    # If a particular driver doesn't have concept of fullscreen it may not support this method.\n    #\n    # @macro about_current\n    #\n    def fullscreen\n      @driver.fullscreen_window(handle)\n    end\n\n    def eql?(other)\n      other.is_a?(self.class) && @session == other.session && @handle == other.handle\n    end\n    alias_method :==, :eql?\n\n    def hash\n      [@session, @handle].hash\n    end\n\n    def inspect\n      \"#<Window @handle=#{@handle.inspect}>\"\n    end\n\n  private\n\n    def wait_for_stable_size(seconds = session.config.default_max_wait_time)\n      res = yield if block_given?\n      timer = Capybara::Helpers.timer(expire_in: seconds)\n      loop do\n        prev_size = size\n        sleep 0.025\n        return res if prev_size == size\n        break if timer.expired?\n      end\n      raise Capybara::WindowError, \"Window size not stable within #{seconds} seconds.\"\n    end\n  end\nend\n"
  },
  {
    "path": "lib/capybara.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'timeout'\nrequire 'nokogiri'\nrequire 'xpath'\nrequire 'forwardable'\nrequire 'capybara/config'\nrequire 'capybara/registration_container'\n\nmodule Capybara\n  class CapybaraError < StandardError; end\n  class DriverNotFoundError < CapybaraError; end\n  class FrozenInTime < CapybaraError; end\n  class ElementNotFound < CapybaraError; end\n  class ModalNotFound < CapybaraError; end\n  class Ambiguous < ElementNotFound; end\n  class ExpectationNotMet < ElementNotFound; end\n  class FileNotFound < CapybaraError; end\n  class UnselectNotAllowed < CapybaraError; end\n  class NotSupportedByDriverError < CapybaraError; end\n  class InfiniteRedirectError < CapybaraError; end\n  class ScopeError < CapybaraError; end\n  class WindowError < CapybaraError; end\n  class ReadOnlyElementError < CapybaraError; end\n\n  class << self\n    extend Forwardable\n\n    # DelegateCapybara global configurations\n    # @!method app\n    #   See {Capybara.configure}\n    # @!method reuse_server\n    #   See {Capybara.configure}\n    # @!method threadsafe\n    #   See {Capybara.configure}\n    # @!method server\n    #   See {Capybara.configure}\n    # @!method default_driver\n    #   See {Capybara.configure}\n    # @!method javascript_driver\n    #   See {Capybara.configure}\n    # @!method use_html5_parsing\n    #   See {Capybara.configure}\n    Config::OPTIONS.each do |method|\n      def_delegators :config, method, \"#{method}=\"\n    end\n\n    # Delegate Capybara global configurations\n    # @!method default_selector\n    #   See {Capybara.configure}\n    # @!method default_max_wait_time\n    #   See {Capybara.configure}\n    # @!method app_host\n    #   See {Capybara.configure}\n    # @!method always_include_port\n    #   See {Capybara.configure}\n    SessionConfig::OPTIONS.each do |method|\n      def_delegators :config, method, \"#{method}=\"\n    end\n\n    ##\n    #\n    # Configure Capybara to suit your needs.\n    #\n    #     Capybara.configure do |config|\n    #       config.run_server = false\n    #       config.app_host   = 'http://www.google.com'\n    #     end\n    #\n    # #### Configurable options\n    #\n    # - **use_html5_parsing** (Boolean = `false`) - When Nokogiri >= 1.12.0 or `nokogumbo` is installed, whether HTML5 parsing will be used for HTML strings.\n    # - **always_include_port** (Boolean = `false`) - Whether the Rack server's port should automatically be inserted into every visited URL\n    #   unless another port is explicitly specified.\n    # - **app_host** (String, `nil`) - The default host to use when giving a relative URL to visit, must be a valid URL e.g. `http://www.example.com`.\n    # - **asset_host** (String = `nil`) - Where dynamic assets are hosted - will be prepended to relative asset locations if present.\n    # - **automatic_label_click** (Boolean = `false`) - Whether {Capybara::Node::Element#choose Element#choose}, {Capybara::Node::Element#check Element#check},\n    #   {Capybara::Node::Element#uncheck Element#uncheck} will attempt to click the associated `<label>` element if the checkbox/radio button are non-visible.\n    # - **automatic_reload** (Boolean = `true`) - Whether to automatically reload elements as Capybara is waiting.\n    # - **default_max_wait_time** (Numeric = `2`) - The maximum number of seconds to wait for asynchronous processes to finish.\n    # - **default_normalize_ws** (Boolean = `false`) - Whether text predicates and matchers use normalize whitespace behavior.\n    # - **default_retry_interval** (Numeric = `0.01`) - The number of seconds to delay the next check in asynchronous processes.\n    # - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.\n    # - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.\n    # - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.\n    # - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).\n    # - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions\n    #   written using the `XPath#is` method.\n    # - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.\n    # - **ignore_hidden_elements** (Boolean = `true`) - Whether to ignore hidden elements on the page.\n    # - **match** (`:one`, `:first`, `:prefer_exact`, `:smart` = `:smart`) - The matching strategy to find nodes.\n    # - **predicates_wait** (Boolean = `true`) - Whether Capybara's predicate matchers use waiting behavior by default.\n    # - **raise_server_errors** (Boolean = `true`) - Should errors raised in the server be raised in the tests?\n    # - **reuse_server** (Boolean = `true`) - Whether to reuse the server thread between multiple sessions using the same app object.\n    # - **run_server** (Boolean = `true`) - Whether to start a Rack server for the given Rack app.\n    # - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},\n    #   {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.\n    # - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.\n    # - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.\n    # - **server_host** (String = \"127.0.0.1\") - The IP address Capybara will bind the application server to. If the test application is to be accessed from an external host, you will want to change this to \"0.0.0.0\" or to a more specific IP address that your test client can reach.\n    # - **server_errors** (Array\\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server\n    #   and {configure raise_server_errors} is `true`.\n    # - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.\n    # - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.\n    # - **w3c_click_offset** (Boolean = 'true') - Whether click offsets should be from element center (true) or top left (false)\n    #\n    # #### DSL Options\n    #\n    # When using `capybara/dsl`, the following options are also available:\n    #\n    # - **default_driver** (Symbol = `:rack_test`) - The name of the driver to use by default.\n    # - **javascript_driver** (Symbol = `:selenium`) - The name of a driver to use for JavaScript enabled tests.\n    #\n    def configure\n      yield config\n    end\n\n    ##\n    #\n    # Register a new driver for Capybara.\n    #\n    #     Capybara.register_driver :rack_test do |app|\n    #       Capybara::RackTest::Driver.new(app)\n    #     end\n    #\n    # @param [Symbol] name                    The name of the new driver\n    # @yield [app]                            This block takes a rack app and returns a Capybara driver\n    # @yieldparam [<Rack>] app                The rack application that this driver runs against. May be nil.\n    # @yieldreturn [Capybara::Driver::Base]   A Capybara driver instance\n    #\n    def register_driver(name, &block)\n      drivers.send(:register, name, block)\n    end\n\n    ##\n    #\n    # Register a new server for Capybara.\n    #\n    #     Capybara.register_server :webrick do |app, port, host|\n    #       require 'rack/handler/webrick'\n    #       Rack::Handler::WEBrick.run(app, ...)\n    #     end\n    #\n    # @param [Symbol] name                    The name of the new driver\n    # @yield [app, port, host]                This block takes a rack app and a port and returns a rack server listening on that port\n    # @yieldparam [<Rack>] app                The rack application that this server will contain.\n    # @yieldparam port                        The port number the server should listen on\n    # @yieldparam host                        The host/ip to bind to\n    #\n    def register_server(name, &block)\n      servers.send(:register, name.to_sym, block)\n    end\n\n    ##\n    #\n    # Add a new selector to Capybara. Selectors can be used by various methods in Capybara\n    # to find certain elements on the page in a more convenient way. For example adding a\n    # selector to find certain table rows might look like this:\n    #\n    #     Capybara.add_selector(:row) do\n    #       xpath { |num| \".//tbody/tr[#{num}]\" }\n    #     end\n    #\n    # This makes it possible to use this selector in a variety of ways:\n    #\n    #     find(:row, 3)\n    #     page.find('table#myTable').find(:row, 3).text\n    #     page.find('table#myTable').has_selector?(:row, 3)\n    #     within(:row, 3) { expect(page).to have_content('$100.000') }\n    #\n    # Here is another example:\n    #\n    #     Capybara.add_selector(:id) do\n    #       xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }\n    #     end\n    #\n    # Note that this particular selector already ships with Capybara.\n    #\n    # @param [Symbol] name    The name of the selector to add\n    # @yield                  A block executed in the context of the new {Capybara::Selector}\n    #\n    def add_selector(name, **options, &block)\n      Capybara::Selector.add(name, **options, &block)\n    end\n\n    ##\n    #\n    # Modify a selector previously created by {Capybara.add_selector}.\n    # For example, adding a new filter to the :button selector to filter based on\n    # button style (a class) might look like this\n    #\n    #     Capybara.modify_selector(:button) do\n    #       filter (:btn_style, valid_values: [:primary, :secondary]) { |node, style| node[:class].split.include? \"btn-#{style}\" }\n    #     end\n    #\n    #\n    # @param [Symbol] name    The name of the selector to modify\n    # @yield                  A block executed in the context of the existing {Capybara::Selector}\n    #\n    def modify_selector(name, &block)\n      Capybara::Selector.update(name, &block)\n    end\n\n    def drivers\n      @drivers ||= RegistrationContainer.new\n    end\n\n    def servers\n      @servers ||= RegistrationContainer.new\n    end\n\n    # Wraps the given string, which should contain an HTML document or fragment\n    # in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},\n    # {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query\n    # any string containing HTML in the exact same way you would query the current document in a Capybara\n    # session.\n    #\n    # @example A single element\n    #     node = Capybara.string('<a href=\"foo\">bar</a>')\n    #     anchor = node.first('a')\n    #     anchor[:href] #=> 'foo'\n    #     anchor.text #=> 'bar'\n    #\n    # @example Multiple elements\n    #     node = Capybara.string <<-HTML\n    #       <ul>\n    #         <li id=\"home\">Home</li>\n    #         <li id=\"projects\">Projects</li>\n    #       </ul>\n    #     HTML\n    #\n    #     node.find('#projects').text # => 'Projects'\n    #     node.has_selector?('li#home', text: 'Home')\n    #     node.has_selector?('#projects')\n    #     node.find('ul').find('li:first-child').text # => 'Home'\n    #\n    # @param [String] html              An html fragment or document\n    # @return [Capybara::Node::Simple]   A node which has Capybara's finders and matchers\n    #\n    def string(html)\n      Capybara::Node::Simple.new(html)\n    end\n\n    ##\n    #\n    # Runs Capybara's default server for the given application and port\n    # under most circumstances you should not have to call this method\n    # manually.\n    #\n    # @param [Rack Application] app    The rack application to run\n    # @param [Integer] port              The port to run the application on\n    #\n    def run_default_server(app, port)\n      servers[:puma].call(app, port, server_host)\n    end\n\n    ##\n    #\n    # @return [Symbol]    The name of the driver currently in use\n    #\n    def current_driver\n      if threadsafe\n        Thread.current.thread_variable_get :capybara_current_driver\n      else\n        @current_driver\n      end || default_driver\n    end\n    alias_method :mode, :current_driver\n\n    def current_driver=(name)\n      if threadsafe\n        Thread.current.thread_variable_set :capybara_current_driver, name\n      else\n        @current_driver = name\n      end\n    end\n\n    ##\n    #\n    # Use the default driver as the current driver\n    #\n    def use_default_driver\n      self.current_driver = nil\n    end\n\n    ##\n    #\n    # Yield a block using a specific driver\n    #\n    def using_driver(driver)\n      previous_driver = Capybara.current_driver\n      Capybara.current_driver = driver\n      yield\n    ensure\n      self.current_driver = previous_driver\n    end\n\n    ##\n    #\n    # Yield a block using a specific wait time\n    #\n    def using_wait_time(seconds)\n      previous_wait_time = Capybara.default_max_wait_time\n      Capybara.default_max_wait_time = seconds\n      yield\n    ensure\n      Capybara.default_max_wait_time = previous_wait_time\n    end\n\n    ##\n    #\n    # The current {Capybara::Session} based on what is set as {app} and {current_driver}.\n    #\n    # @return [Capybara::Session]     The currently used session\n    #\n    def current_session\n      specified_session || session_pool[\"#{current_driver}:#{session_name}:#{app.object_id}\"]\n    end\n\n    ##\n    #\n    # Reset sessions, cleaning out the pool of sessions. This will remove any session information such\n    # as cookies.\n    #\n    def reset_sessions!\n      # reset in reverse so sessions that started servers are reset last\n      session_pool.reverse_each { |_mode, session| session.reset! }\n    end\n    alias_method :reset!, :reset_sessions!\n\n    ##\n    #\n    # The current session name.\n    #\n    # @return [Symbol]    The name of the currently used session.\n    #\n    def session_name\n      if threadsafe\n        Thread.current.thread_variable_get(:capybara_session_name) ||\n          Thread.current.thread_variable_set(:capybara_session_name, :default)\n      else\n        @session_name ||= :default\n      end\n    end\n\n    def session_name=(name)\n      if threadsafe\n        Thread.current.thread_variable_set :capybara_session_name, name\n      else\n        @session_name = name\n      end\n    end\n\n    ##\n    #\n    # Yield a block using a specific session name or {Capybara::Session} instance.\n    #\n    def using_session(name_or_session, &block)\n      previous_session = current_session\n      previous_session_info = {\n        specified_session: specified_session,\n        session_name: session_name,\n        current_driver: current_driver,\n        app: app\n      }\n      self.specified_session = self.session_name = nil\n      if name_or_session.is_a? Capybara::Session\n        self.specified_session = name_or_session\n      else\n        self.session_name = name_or_session\n      end\n\n      if block.arity.zero?\n        yield\n      else\n        yield current_session, previous_session\n      end\n    ensure\n      self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)\n      self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe\n    end\n\n    ##\n    #\n    # Parse raw html into a document using Nokogiri, and adjust textarea contents as defined by the spec.\n    #\n    # @param [String] html              The raw html\n    # @return [Nokogiri::HTML::Document]      HTML document\n    #\n    def HTML(html) # rubocop:disable Naming/MethodName\n      # Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use\n      html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing\n        [Nokogiri::HTML5, true]\n      else\n        [defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]\n      end\n\n      html_parser.parse(html).tap do |document|\n        document.xpath('//template').each do |template|\n          # template elements content is not part of the document\n          template.inner_html = ''\n        end\n        document.xpath('//textarea').each do |textarea|\n          # The Nokogiri HTML5 parser already returns spec compliant contents\n          textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix(\"\\n\")\n        end\n      end\n    end\n\n    def session_options\n      config.session_options\n    end\n\n  private\n\n    def config\n      @config ||= Capybara::Config.new\n    end\n\n    def session_pool\n      @session_pool ||= Hash.new do |hash, name|\n        hash[name] = Capybara::Session.new(current_driver, app)\n      end\n    end\n\n    def specified_session\n      if threadsafe\n        Thread.current.thread_variable_get :capybara_specified_session\n      else\n        @specified_session ||= nil\n      end\n    end\n\n    def specified_session=(session)\n      if threadsafe\n        Thread.current.thread_variable_set :capybara_specified_session, session\n      else\n        @specified_session = session\n      end\n    end\n  end\n\n  self.default_driver = nil\n  self.current_driver = nil\n  self.server_host = nil\n\n  module Driver; end\n  module RackTest; end\n  module Selenium; end\n\n  require 'capybara/helpers'\n  require 'capybara/session'\n  require 'capybara/window'\n  require 'capybara/server'\n  require 'capybara/selector'\n  require 'capybara/result'\n  require 'capybara/version'\n\n  require 'capybara/queries/base_query'\n  require 'capybara/queries/selector_query'\n  require 'capybara/queries/text_query'\n  require 'capybara/queries/title_query'\n  require 'capybara/queries/current_path_query'\n  require 'capybara/queries/match_query'\n  require 'capybara/queries/ancestor_query'\n  require 'capybara/queries/sibling_query'\n  require 'capybara/queries/style_query'\n  require 'capybara/queries/active_element_query'\n\n  require 'capybara/node/finders'\n  require 'capybara/node/matchers'\n  require 'capybara/node/actions'\n  require 'capybara/node/document_matchers'\n  require 'capybara/node/simple'\n  require 'capybara/node/base'\n  require 'capybara/node/element'\n  require 'capybara/node/document'\n\n  require 'capybara/driver/base'\n  require 'capybara/driver/node'\n\n  require 'capybara/rack_test/driver'\n  require 'capybara/rack_test/node'\n  require 'capybara/rack_test/form'\n  require 'capybara/rack_test/browser'\n  require 'capybara/rack_test/css_handlers'\n\n  require 'capybara/selenium/node'\n  require 'capybara/selenium/driver'\nend\n\nrequire 'capybara/registrations/servers'\nrequire 'capybara/registrations/drivers'\n\nCapybara.configure do |config|\n  config.always_include_port = false\n  config.run_server = true\n  config.server = :default\n  config.default_selector = :css\n  config.default_max_wait_time = 2\n  config.default_retry_interval = 0.01\n  config.ignore_hidden_elements = true\n  config.default_host = 'http://www.example.com'\n  config.automatic_reload = true\n  config.match = :smart\n  config.exact = false\n  config.exact_text = false\n  config.raise_server_errors = true\n  config.server_errors = [Exception]\n  config.visible_text_only = false\n  config.automatic_label_click = false\n  config.enable_aria_label = false\n  config.enable_aria_role = false\n  config.reuse_server = true\n  config.default_set_options = {}\n  config.test_id = nil\n  config.predicates_wait = true\n  config.default_normalize_ws = false\n  config.use_html5_parsing = false\n  config.w3c_click_offset = true\nend\n"
  },
  {
    "path": "spec/basic_node_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara do\n  include Capybara::RSpecMatchers\n\n  describe '.string' do\n    let :string do\n      described_class.string <<-STRING\n        <html>\n          <head>\n            <title>simple_node</title>\n          </head>\n          <body>\n            <svg><title>not document title</title></svg>\n            <div id=\"page\">\n              <div id=\"content\">\n                <h1 data=\"fantastic\">Totally awesome</h1>\n                <p>Yes it is</p>\n              </div>\n\n              <form>\n                <input type=\"text\" name=\"bleh\" disabled=\"disabled\"/>\n                <input type=\"text\" name=\"meh\"/>\n              </form>\n\n              <div id=\"footer\">\n                <p>c2010</p>\n                <p>Jonas Nicklas</p>\n                <input type=\"text\" name=\"foo\" value=\"bar\"/>\n                <select name=\"animal\">\n                  <option>Monkey</option>\n                  <option selected=\"selected\">Capybara</option>\n                </select>\n              </div>\n\n              <div id=\"hidden\" style=\"display: none\">\n                <p id=\"secret\">Secret</p>\n              </div>\n\n              <section>\n                <div class=\"subsection\"></div>\n              </section>\n            </div>\n          </body>\n        </html>\n      STRING\n    end\n\n    it 'allows using matchers' do\n      expect(string).to have_css('#page')\n      expect(string).not_to have_css('#does-not-exist')\n    end\n\n    it 'allows using custom matchers' do\n      described_class.add_selector :lifeform do\n        xpath { |name| \".//option[contains(.,'#{name}')]\" }\n      end\n      expect(string).to have_selector(:id, 'page')\n      expect(string).not_to have_selector(:id, 'does-not-exist')\n      expect(string).to have_selector(:lifeform, 'Monkey')\n      expect(string).not_to have_selector(:lifeform, 'Gorilla')\n    end\n\n    it 'allows custom matcher using css' do\n      described_class.add_selector :section do\n        css { |css_class| \"section .#{css_class}\" }\n      end\n      expect(string).to     have_selector(:section, 'subsection')\n      expect(string).not_to have_selector(:section, 'section_8')\n    end\n\n    it 'allows using matchers with text option' do\n      expect(string).to have_css('h1', text: 'Totally awesome')\n      expect(string).not_to have_css('h1', text: 'Not so awesome')\n    end\n\n    it 'allows finding only visible nodes' do\n      expect(string.all(:css, '#secret', visible: true)).to be_empty\n      expect(string.all(:css, '#secret', visible: false).size).to eq(1)\n    end\n\n    it 'allows finding elements and extracting text from them' do\n      expect(string.find('//h1').text).to eq('Totally awesome')\n    end\n\n    it 'allows finding elements and extracting attributes from them' do\n      expect(string.find('//h1')[:data]).to eq('fantastic')\n    end\n\n    it 'allows finding elements and extracting the tag name from them' do\n      expect(string.find('//h1').tag_name).to eq('h1')\n    end\n\n    it 'allows finding elements and extracting the path' do\n      expect(string.find('//h1').path).to eq('/html/body/div/div[1]/h1')\n    end\n\n    it 'allows finding elements and extracting the value' do\n      expect(string.find('//div/input').value).to eq('bar')\n      expect(string.find('//select').value).to eq('Capybara')\n    end\n\n    it 'allows finding elements and checking if they are visible' do\n      expect(string.find('//h1')).to be_visible\n      expect(string.find(:css, '#secret', visible: false)).not_to be_visible\n    end\n\n    it 'allows finding elements and checking if they are disabled' do\n      expect(string.find('//form/input[@name=\"bleh\"]')).to be_disabled\n      expect(string.find('//form/input[@name=\"meh\"]')).not_to be_disabled\n    end\n\n    it 'allows finding siblings' do\n      h1 = string.find(:css, 'h1')\n      expect(h1).to have_sibling(:css, 'p', text: 'Yes it is')\n      expect(h1).not_to have_sibling(:css, 'p', text: 'Jonas Nicklas')\n    end\n\n    it 'allows finding ancestor' do\n      h1 = string.find(:css, 'h1')\n      expect(h1).to have_ancestor(:css, '#content')\n      expect(h1).not_to have_ancestor(:css, '#footer')\n    end\n\n    it 'drops illegal fragments when using gumbo' do\n      skip 'libxml is less strict than Gumbo' unless Nokogiri.respond_to?(:HTML5)\n      described_class.use_html5_parsing = true\n      expect(described_class.string('<td>1</td>')).not_to have_css('td')\n    end\n\n    it 'can disable use of HTML5 parsing' do\n      skip \"Test doesn't make sense unlesss HTML5 parsing is loaded (Nokogumbo or Nokogiri >= 1.12.0)\" unless Nokogiri.respond_to?(:HTML5)\n      described_class.use_html5_parsing = false\n      expect(described_class.string('<td>1</td>')).to have_css('td')\n    end\n\n    describe '#title' do\n      it 'returns the page title' do\n        expect(string.title).to eq('simple_node')\n      end\n    end\n\n    describe '#has_title?' do\n      it 'returns whether the page has the given title' do\n        expect(string.has_title?('simple_node')).to be true\n        expect(string.has_title?('monkey')).to be false\n      end\n\n      it 'allows regexp matches' do\n        expect(string.has_title?(/s[a-z]+_node/)).to be true\n        expect(string.has_title?(/monkey/)).to be false\n      end\n    end\n\n    describe '#has_no_title?' do\n      it 'returns whether the page does not have the given title' do\n        expect(string.has_no_title?('simple_node')).to be false\n        expect(string.has_no_title?('monkey')).to be true\n      end\n\n      it 'allows regexp matches' do\n        expect(string.has_no_title?(/s[a-z]+_node/)).to be false\n        expect(string.has_no_title?(/monkey/)).to be true\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/capybara_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara do\n  describe 'default_max_wait_time' do\n    before { @previous_default_time = described_class.default_max_wait_time }\n\n    after { described_class.default_max_wait_time = @previous_default_time } # rubocop:disable RSpec/InstanceVariable\n\n    it 'should be changeable' do\n      expect(described_class.default_max_wait_time).not_to eq(5)\n      described_class.default_max_wait_time = 5\n      expect(described_class.default_max_wait_time).to eq(5)\n    end\n  end\n\n  describe 'default_retry_interval' do\n    before { @previous_default_interval = described_class.default_retry_interval }\n\n    after { described_class.default_retry_interval = @previous_default_interval } # rubocop:disable RSpec/InstanceVariable\n\n    it 'should be changeable' do\n      expect(described_class.default_retry_interval).not_to eq(0.1)\n      described_class.default_retry_interval = 0.1\n      expect(described_class.default_retry_interval).to eq(0.1)\n    end\n  end\n\n  describe '.register_driver' do\n    it 'should add a new driver' do\n      described_class.register_driver :schmoo do |app|\n        Capybara::RackTest::Driver.new(app)\n      end\n      session = Capybara::Session.new(:schmoo, TestApp)\n      session.visit('/')\n      expect(session.body).to include('Hello world!')\n    end\n  end\n\n  describe '.register_server' do\n    it 'should add a new server' do\n      described_class.register_server :blob do |_app, _port, _host|\n        # do nothing\n      end\n\n      expect(described_class.servers[:blob]).to be_truthy\n    end\n  end\n\n  describe '.server' do\n    after do\n      described_class.server = :default\n    end\n\n    it 'should default to a proc that calls run_default_server' do\n      mock_app = Object.new\n      allow(described_class).to receive(:run_default_server).and_return(true)\n      described_class.server.call(mock_app, 8000)\n      expect(described_class).to have_received(:run_default_server).with(mock_app, 8000)\n    end\n\n    it 'should return a custom server proc' do\n      server = ->(_app, _port) {}\n      described_class.register_server :custom, &server\n      described_class.server = :custom\n      expect(described_class.server).to eq(server)\n    end\n\n    it 'should have :webrick registered' do\n      expect(described_class.servers[:webrick]).not_to be_nil\n    end\n\n    it 'should have :puma registered' do\n      expect(described_class.servers[:puma]).not_to be_nil\n    end\n  end\n\n  describe 'server=' do\n    after do\n      described_class.server = :default\n    end\n\n    it 'accepts a proc' do\n      server = ->(_app, _port) {}\n      described_class.server = server\n      expect(described_class.server).to eq server\n    end\n  end\n\n  describe 'app_host' do\n    after do\n      described_class.app_host = nil\n    end\n\n    it 'should warn if not a valid URL' do\n      expect { described_class.app_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\\.app_host should be set to a url/)\n    end\n\n    it 'should not warn if a valid URL' do\n      expect { described_class.app_host = 'http://www.example.com' }.not_to raise_error\n    end\n\n    it 'should not warn if nil' do\n      expect { described_class.app_host = nil }.not_to raise_error\n    end\n  end\n\n  describe 'default_host' do\n    around do |test|\n      old_default = described_class.default_host\n      test.run\n      described_class.default_host = old_default\n    end\n\n    it 'should raise if not a valid URL' do\n      expect { described_class.default_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\\.default_host should be set to a url/)\n    end\n\n    it 'should not warn if a valid URL' do\n      expect { described_class.default_host = 'http://www.example.com' }.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/counter_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Server::Middleware::Counter do\n  let(:counter) { described_class.new }\n  let(:uri) { '/example' }\n\n  describe '#increment' do\n    it 'successfully' do\n      counter.increment(uri)\n      expect(counter).to be_positive\n    end\n  end\n\n  describe '#decrement' do\n    before do\n      counter.increment(uri)\n    end\n\n    context 'successfully' do\n      it 'with same uri' do\n        expect(counter).to be_positive\n        counter.decrement(uri)\n        expect(counter).not_to be_positive\n      end\n\n      it 'with changed uri' do\n        expect(counter).to be_positive\n        counter.decrement('/')\n        expect(counter).not_to be_positive\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/css_builder_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\n# rubocop:disable RSpec/InstanceVariable\nRSpec.describe Capybara::Selector::CSSBuilder do\n  let :builder do\n    described_class.new(@css)\n  end\n\n  context 'add_attribute_conditions' do\n    it 'adds a single string condition to a single selector' do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(random: 'abc')\n      expect(selector).to eq %(div[random='abc'])\n    end\n\n    it 'adds multiple string conditions to a single selector' do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(random: 'abc', other: 'def')\n      expect(selector).to eq %(div[random='abc'][other='def'])\n    end\n\n    it 'adds a single string condition to a multiple selector' do\n      @css = 'div, ul'\n      selector = builder.add_attribute_conditions(random: 'abc')\n      expect(selector).to eq %(div[random='abc'], ul[random='abc'])\n    end\n\n    it 'adds multiple string conditions to a multiple selector' do\n      @css = 'div, ul'\n      selector = builder.add_attribute_conditions(random: 'abc', other: 'def')\n      expect(selector).to eq %(div[random='abc'][other='def'], ul[random='abc'][other='def'])\n    end\n\n    it 'adds simple regexp conditions to a single selector' do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(random: /abc/, other: /def/)\n      expect(selector).to eq %(div[random*='abc'][other*='def'])\n    end\n\n    it 'adds wildcard regexp conditions to a single selector' do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(random: /abc.*def/, other: /def.*ghi/)\n      expect(selector).to eq %(div[random*='abc'][random*='def'][other*='def'][other*='ghi'])\n    end\n\n    it 'adds alternated regexp conditions to a single selector' do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(random: /abc|def/, other: /def|ghi/)\n      expect(selector).to eq %(div[random*='abc'][other*='def'], div[random*='abc'][other*='ghi'], div[random*='def'][other*='def'], div[random*='def'][other*='ghi'])\n    end\n\n    it 'adds alternated regexp conditions to a multiple selector' do\n      @css = 'div,ul'\n      selector = builder.add_attribute_conditions(other: /def.*ghi|jkl/)\n      expect(selector).to eq %(div[other*='def'][other*='ghi'], div[other*='jkl'], ul[other*='def'][other*='ghi'], ul[other*='jkl'])\n    end\n\n    it \"returns original selector when regexp can't be substringed\" do\n      @css = 'div'\n      selector = builder.add_attribute_conditions(other: /.+/)\n      expect(selector).to eq 'div'\n    end\n\n    context ':class' do\n      it 'handles string with CSS .' do\n        @css = 'a'\n        selector = builder.add_attribute_conditions(class: 'my_class')\n        expect(selector).to eq 'a.my_class'\n      end\n\n      it 'handles negated string with CSS .' do\n        @css = 'a'\n        selector = builder.add_attribute_conditions(class: '!my_class')\n        expect(selector).to eq 'a:not(.my_class)'\n      end\n\n      it 'handles array of string with CSS .' do\n        @css = 'a'\n        selector = builder.add_attribute_conditions(class: %w[my_class my_other_class])\n        expect(selector).to eq 'a.my_class.my_other_class'\n      end\n\n      it 'handles array of string with CSS . when negated included' do\n        @css = 'a'\n        selector = builder.add_attribute_conditions(class: %w[my_class !my_other_class])\n        expect(selector).to eq 'a.my_class:not(.my_other_class)'\n      end\n    end\n\n    context ':id' do\n      it 'handles string with CSS #' do\n        @css = 'ul'\n        selector = builder.add_attribute_conditions(id: 'my_id')\n        expect(selector).to eq 'ul#my_id'\n      end\n    end\n  end\nend\n# rubocop:enable RSpec/InstanceVariable\n"
  },
  {
    "path": "spec/css_splitter_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Selector::CSS::Splitter do\n  let :splitter do\n    described_class.new\n  end\n\n  context 'split not needed' do\n    it 'normal CSS selector' do\n      css = 'div[id=\"abc\"]'\n      expect(splitter.split(css)).to eq [css]\n    end\n\n    it 'comma in strings' do\n      css = 'div[id=\"a,bc\"]'\n      expect(splitter.split(css)).to eq [css]\n    end\n\n    it 'comma in pseudo-selector' do\n      css = 'div.class1:not(.class1, .class2)'\n      expect(splitter.split(css)).to eq [css]\n    end\n  end\n\n  context 'split needed' do\n    it 'root level comma' do\n      css = 'div.class1, span, p.class2'\n      expect(splitter.split(css)).to eq ['div.class1', 'span', 'p.class2']\n    end\n\n    it 'root level comma when quotes and pseudo selectors' do\n      css = 'div.class1[id=\"abc\\\\\"def,ghi\"]:not(.class3, .class4), span[id=\\'a\"c\\\\\\'de\\'], section, #abc\\\\,def'\n      expect(splitter.split(css)).to eq ['div.class1[id=\"abc\\\\\"def,ghi\"]:not(.class3, .class4)', 'span[id=\\'a\"c\\\\\\'de\\']', 'section', '#abc\\\\,def']\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dsl_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/dsl'\n\nclass TestClass\n  include Capybara::DSL\nend\n\nCapybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[\n  js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation shadow_dom active_element\n] do |example|\n  case example.metadata[:full_description]\n  when /has_css\\? should support case insensitive :class and :id options/\n    pending \"Nokogiri doesn't support case insensitive CSS attribute matchers\"\n  when /#click_button should follow permanent redirects that maintain method/\n    pending \"Rack < 2 doesn't support 308\" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')\n  when /#attach_file with multipart form should send prior hidden field if no file submitted/\n    skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')\n  when /popover/\n    skip \"Rack-test driver doesn't support popover functionality\"\n  end\nend\n\nRSpec.describe Capybara::DSL do\n  before do\n    Capybara.use_default_driver\n  end\n\n  after do\n    Capybara.session_name = nil\n    Capybara.default_driver = nil\n    Capybara.javascript_driver = nil\n    Capybara.use_default_driver\n    Capybara.app = TestApp\n  end\n\n  describe '#default_driver' do\n    it 'should default to rack_test' do\n      expect(Capybara.default_driver).to eq(:rack_test)\n    end\n\n    it 'should be changeable' do\n      Capybara.default_driver = :culerity\n      expect(Capybara.default_driver).to eq(:culerity)\n    end\n  end\n\n  describe '#current_driver' do\n    it 'should default to the default driver' do\n      expect(Capybara.current_driver).to eq(:rack_test)\n      Capybara.default_driver = :culerity\n      expect(Capybara.current_driver).to eq(:culerity)\n    end\n\n    it 'should be changeable' do\n      Capybara.current_driver = :culerity\n      expect(Capybara.current_driver).to eq(:culerity)\n    end\n  end\n\n  describe '#javascript_driver' do\n    it 'should default to selenium' do\n      expect(Capybara.javascript_driver).to eq(:selenium)\n    end\n\n    it 'should be changeable' do\n      Capybara.javascript_driver = :culerity\n      expect(Capybara.javascript_driver).to eq(:culerity)\n    end\n  end\n\n  describe '#use_default_driver' do\n    it 'should restore the default driver' do\n      Capybara.current_driver = :culerity\n      Capybara.use_default_driver\n      expect(Capybara.current_driver).to eq(:rack_test)\n    end\n  end\n\n  describe '#using_driver' do\n    before do\n      expect(Capybara.current_driver).not_to eq(:selenium) # rubocop:disable RSpec/ExpectInHook\n    end\n\n    it 'should set the driver using Capybara.current_driver=' do\n      driver = nil\n      Capybara.using_driver(:selenium) { driver = Capybara.current_driver }\n      expect(driver).to eq(:selenium)\n    end\n\n    it 'should return the driver to default if it has not been changed' do\n      Capybara.using_driver(:selenium) do\n        expect(Capybara.current_driver).to eq(:selenium)\n      end\n      expect(Capybara.current_driver).to eq(Capybara.default_driver)\n    end\n\n    it 'should reset the driver even if an exception occurs' do\n      driver_before_block = Capybara.current_driver\n      begin\n        Capybara.using_driver(:selenium) { raise 'ohnoes!' }\n      rescue Exception # rubocop:disable Lint/RescueException,Lint/SuppressedException\n      end\n      expect(Capybara.current_driver).to eq(driver_before_block)\n    end\n\n    it 'should return the driver to what it was previously' do\n      Capybara.current_driver = :selenium\n      Capybara.using_driver(:culerity) do\n        Capybara.using_driver(:rack_test) do\n          expect(Capybara.current_driver).to eq(:rack_test)\n        end\n        expect(Capybara.current_driver).to eq(:culerity)\n      end\n      expect(Capybara.current_driver).to eq(:selenium)\n    end\n\n    it 'should yield the passed block' do\n      called = false\n      Capybara.using_driver(:selenium) { called = true }\n      expect(called).to be(true)\n    end\n  end\n\n  # rubocop:disable RSpec/InstanceVariable\n  describe '#using_wait_time' do\n    before { @previous_wait_time = Capybara.default_max_wait_time }\n\n    after { Capybara.default_max_wait_time = @previous_wait_time }\n\n    it 'should switch the wait time and switch it back' do\n      in_block = nil\n      Capybara.using_wait_time 6 do\n        in_block = Capybara.default_max_wait_time\n      end\n      expect(in_block).to eq(6)\n      expect(Capybara.default_max_wait_time).to eq(@previous_wait_time)\n    end\n\n    it 'should ensure wait time is reset' do\n      expect do\n        Capybara.using_wait_time 6 do\n          raise 'hell'\n        end\n      end.to raise_error(RuntimeError, 'hell')\n      expect(Capybara.default_max_wait_time).to eq(@previous_wait_time)\n    end\n  end\n  # rubocop:enable RSpec/InstanceVariable\n\n  describe '#app' do\n    it 'should be changeable' do\n      Capybara.app = 'foobar'\n      expect(Capybara.app).to eq('foobar')\n    end\n  end\n\n  describe '#current_session' do\n    it 'should choose a session object of the current driver type' do\n      expect(Capybara.current_session).to be_a(Capybara::Session)\n    end\n\n    it 'should use #app as the application' do\n      Capybara.app = proc {}\n      expect(Capybara.current_session.app).to eq(Capybara.app)\n    end\n\n    it 'should change with the current driver' do\n      expect(Capybara.current_session.mode).to eq(:rack_test)\n      Capybara.current_driver = :selenium\n      expect(Capybara.current_session.mode).to eq(:selenium)\n    end\n\n    it 'should be persistent even across driver changes' do\n      object_id = Capybara.current_session.object_id\n      expect(Capybara.current_session.object_id).to eq(object_id)\n      Capybara.current_driver = :selenium\n      expect(Capybara.current_session.mode).to eq(:selenium)\n      expect(Capybara.current_session.object_id).not_to eq(object_id)\n\n      Capybara.current_driver = :rack_test\n      expect(Capybara.current_session.object_id).to eq(object_id)\n    end\n\n    it 'should change when changing application' do\n      object_id = Capybara.current_session.object_id\n      expect(Capybara.current_session.object_id).to eq(object_id)\n      Capybara.app = proc {}\n      expect(Capybara.current_session.object_id).not_to eq(object_id)\n      expect(Capybara.current_session.app).to eq(Capybara.app)\n    end\n\n    it 'should change when the session name changes' do\n      object_id = Capybara.current_session.object_id\n      Capybara.session_name = :administrator\n      expect(Capybara.session_name).to eq(:administrator)\n      expect(Capybara.current_session.object_id).not_to eq(object_id)\n      Capybara.session_name = :default\n      expect(Capybara.session_name).to eq(:default)\n      expect(Capybara.current_session.object_id).to eq(object_id)\n    end\n  end\n\n  describe '#using_session' do\n    it 'should change the session name for the duration of the block' do\n      expect(Capybara.session_name).to eq(:default)\n      Capybara.using_session(:administrator) do\n        expect(Capybara.session_name).to eq(:administrator)\n      end\n      expect(Capybara.session_name).to eq(:default)\n    end\n\n    it 'should reset the session to the default, even if an exception occurs' do\n      begin\n        Capybara.using_session(:raise) do\n          raise\n        end\n      rescue Exception # rubocop:disable Lint/RescueException,Lint/SuppressedException\n      end\n      expect(Capybara.session_name).to eq(:default)\n    end\n\n    it 'should yield the passed block' do\n      called = false\n      Capybara.using_session(:administrator) { called = true }\n      expect(called).to be(true)\n    end\n\n    it 'should be nestable' do\n      Capybara.using_session(:outer) do\n        expect(Capybara.session_name).to eq(:outer)\n        Capybara.using_session(:inner) do\n          expect(Capybara.session_name).to eq(:inner)\n        end\n        expect(Capybara.session_name).to eq(:outer)\n      end\n      expect(Capybara.session_name).to eq(:default)\n    end\n\n    it 'should allow a session object' do\n      original_session = Capybara.current_session\n      new_session = Capybara::Session.new(:rack_test, proc {})\n      Capybara.using_session(new_session) do\n        expect(Capybara.current_session).to eq(new_session)\n      end\n      expect(Capybara.current_session).to eq(original_session)\n    end\n\n    it 'should pass the new session if block accepts' do\n      original_session = Capybara.current_session\n      Capybara.using_session(:administrator) do |admin_session, prev_session|\n        expect(admin_session).to be(Capybara.current_session)\n        expect(prev_session).to be(original_session)\n        expect(prev_session).not_to be(admin_session)\n      end\n    end\n  end\n\n  describe '#session_name' do\n    it 'should default to :default' do\n      expect(Capybara.session_name).to eq(:default)\n    end\n  end\n\n  describe 'the DSL' do\n    let(:session) { Class.new { include Capybara::DSL }.new }\n\n    it 'should be possible to include it in another class' do\n      session.visit('/with_html')\n      session.click_link('ullamco')\n      expect(session.body).to include('Another World')\n    end\n\n    it \"should provide a 'page' shortcut for more expressive tests\" do\n      session.page.visit('/with_html')\n      session.page.click_link('ullamco')\n      expect(session.page.body).to include('Another World')\n    end\n\n    it \"should provide an 'using_session' shortcut\" do\n      allow(Capybara).to receive(:using_session)\n      session.using_session(:name)\n      expect(Capybara).to have_received(:using_session).with(:name)\n    end\n\n    it \"should provide a 'using_wait_time' shortcut\" do\n      allow(Capybara).to receive(:using_wait_time)\n      session.using_wait_time(6)\n      expect(Capybara).to have_received(:using_wait_time).with(6)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/filter_set_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Selector::FilterSet do\n  after do\n    described_class.remove(:test)\n  end\n\n  it 'allows node filters' do\n    fs = described_class.add(:test) do\n      node_filter(:node_test, :boolean) { |_node, _value| true }\n      expression_filter(:expression_test, :boolean) { |_expr, _value| true }\n    end\n\n    expect(fs.node_filters.keys).to include(:node_test)\n    expect(fs.node_filters.keys).not_to include(:expression_test)\n  end\n\n  it 'allows expression filters' do\n    fs = described_class.add(:test) do\n      node_filter(:node_test, :boolean) { |_node, _value| true }\n      expression_filter(:expression_test, :boolean) { |_expr, _value| true }\n    end\n\n    expect(fs.expression_filters.keys).to include(:expression_test)\n    expect(fs.expression_filters.keys).not_to include(:node_test)\n  end\n\n  it 'allows node filter and expression filter with the same name' do\n    fs = described_class.add(:test) do\n      node_filter(:test, :boolean) { |_node, _value| true }\n      expression_filter(:test, :boolean) { |_expr, _value| true }\n    end\n\n    expect(fs.expression_filters[:test]).not_to eq fs.node_filters[:test]\n  end\n\n  it 'allows `filter` as an alias of `node_filter`' do\n    fs = described_class.add(:test) do\n      filter(:node_test, :boolean) { |_node, _value| true }\n    end\n\n    expect(fs.node_filters.keys).to include(:node_test)\n  end\nend\n"
  },
  {
    "path": "spec/fixtures/capybara.csv",
    "content": "test, mime-type, file\n"
  },
  {
    "path": "spec/fixtures/certificate.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEITCCAwmgAwIBAgIJALROkwd1gZHQMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV\nBAYTAlVTMQswCQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMT\nDWNhcHliYXJhLnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNv\nbTAeFw0xODA1MDEyMDI5NDVaFw0yODA0MjgyMDI5NDVaMGgxCzAJBgNVBAYTAlVT\nMQswCQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMTDWNhcHli\nYXJhLnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7icqMv9uApxRXlcIQ3hSEfmULk\n7CLT1aUAjEmTiqy8TkFqOeSuA3elnbVBhOW+emrb1uUyje20LvEOHbqYYw90ezlV\njqNWUapawqjxb+q7KVNpA5uDCtOHIC/1Z1kxQ+yZP/8St4SvnLGUMsUhu0h+ywJa\niGZ2xy8wdfjABUiUImRESdNkT7Xs0wxQGY0/FZ4K5Sec4kroOuvdxKKhyf5Js5xS\nNRv2tXSMWlKHbYEvYzsVtFgv/4GjqN4wVvbfJmsS8thcyrSYSMN7eE0R6dcbJaLM\nP/GTiw669zPJP164K84QoabLClgwyG+7mqjm7jutq9qXipwyrGsf/WR5fkUCAwEA\nAaOBzTCByjAdBgNVHQ4EFgQU4ut9c0oB2OGMlN/nvn0Y7twBzJowgZoGA1UdIwSB\nkjCBj4AU4ut9c0oB2OGMlN/nvn0Y7twBzJqhbKRqMGgxCzAJBgNVBAYTAlVTMQsw\nCQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMTDWNhcHliYXJh\nLnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNvbYIJALROkwd1\ngZHQMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAANtqdDrdehBt20s\nIVOsVzOp+tJI8pn6G62WJcZWGsvLLfx6Y6eJSP24r5NW4v39cqCgE76J2znzKxeo\nVIShAJ1SLodR0GwzFGsl3TVKVoce6gBWZNXgkZyJTNqKGWeme8CH1EG3TqYlcybt\nEXWLQ6wKndD+uHJIfqUy7HfaUv+TghJGLkv8QYqcAWILQko4xqZ1NULDQ2uhjxei\noaQlK9teHlVaH87dONesAg3f5rh9j6nvzGiC/T8ycdEhn/DxJMxRS2+mVZqKkk7U\n60+e9Foc6qTW8UaMShIFYMspoRnr9baBxzxh9V9LZznwqVTf3vuEIck2l2j2KL/R\nSOBenCM=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "spec/fixtures/key.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvuJyoy/24CnFFeVwhDeFIR+ZQuTsItPVpQCMSZOKrLxOQWo5\n5K4Dd6WdtUGE5b56atvW5TKN7bQu8Q4duphjD3R7OVWOo1ZRqlrCqPFv6rspU2kD\nm4MK04cgL/VnWTFD7Jk//xK3hK+csZQyxSG7SH7LAlqIZnbHLzB1+MAFSJQiZERJ\n02RPtezTDFAZjT8VngrlJ5ziSug6693EoqHJ/kmznFI1G/a1dIxaUodtgS9jOxW0\nWC//gaOo3jBW9t8maxLy2FzKtJhIw3t4TRHp1xslosw/8ZOLDrr3M8k/XrgrzhCh\npssKWDDIb7uaqObuO62r2peKnDKsax/9ZHl+RQIDAQABAoIBABhZepYmgC+IJIPu\niLPVAT6AcWR/H0AyFYa+0yZvk7kFLFZb3pa1O+v/TGbavMEx0xvef0Mtd71ixrop\nOtGarshB65Ycu91KHZDFkx9J7STcSyFAvB0SUkc5bXmwrEZMaoW75tX65T4fyLU+\nWlubOfC9e9gJBG1NqYrze5kHpaTkR8pBaSxECns5y2HLaMvs1t1kK7snqtGHFRAb\ndeAUl0ONENaO6PF797yM3bsIEgnljdKvaVP3kYq/eAzH4jyw+qG/xq0bZ+nalJzM\nIL7xRSR/Yak7WZ3QUh99t3dng/z3De4yvhBLq/mc2mIVvt7aERPo/aDG4SrmQ9Jw\nf1GUT+ECgYEA+i96w2zPHkq0djuuhNaa/R0vybD9hVCdB7enQ8skBzQAQyhp9X9W\nby38VAbFRVIMrzdfbvwSFrE3Nd9BvyLWl16G+MVu+hq0jhM9p44a62vXvfgQmfFh\niXyGkzCTufeLEzOFnP8S+ezacodK1hbQTjllUndn6NUhXcbfozTPfx8CgYEAw1Il\nxqfU7NkVX6UP/FvTx9aBKqwrD8YOPn9nj26Q45zVbmHJZZIvywlsMDCiJ6JJawEa\nGSkiZTDpypEvS/2UtLEY0zfbSbQGkBTnagHIFAuVh0AD1EP+kCcnrxA5Vjr8v0WE\nB0HBfMgoZxa8rmHMpPhrlCCo1ectRgu+dgzEKhsCgYAQ17lwBpc69tSHUSVClCAD\nAkABWAT5QKARsO91xOs8AOgznTjk6hmrinD+RyZosEliUlv+YMHm/S82VT1b3MCN\nmDOF8+SwubOGDQ2NhieRycTQaS7U7kcetl9o8VBAqMWYGVPZaeKhKKzcIPeMyiRj\n38FOd/Nq3U5NveG4XwnJCQKBgGrzmnfTAsbGf+uliMFYzviIPqZNLC8w9i/Gt8BU\nfMYF5ODSbuNNTxpQiItCtigZtzX+nnnUil76j6o6IbnsmvbuWneeCFetWkKfD7B+\nVT6UsUYkCXS73rK0nghATAUpu6hIumj22qonN+hrDNo390UGOnIcCBdIxQOr/pjJ\nmMitAoGAB3tFzlzZHpCE38IqdHL7CKIML9cYJSOm07nFIEUAKN2bUHGsvMH/tMS1\nI3hyeHxMmYCrOLn7xLqiOVgRjbYS9JiQVdDojqeSvvnLCtY9/lHWi50pqbPfwyfK\nOg6QoFyxjBEsoSilc6dai58VTO6ufhoJXbXX9PcIl7le4dVPnzE=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "spec/fixtures/selenium_driver_rspec_failure.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\n\nRSpec.describe Capybara::Selenium::Driver do\n  it 'should exit with a non-zero exit status' do\n    options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }\n    browser = described_class.new(TestApp, options).browser\n    expect(browser).to be_truthy\n    expect(true).to be(false) # rubocop:disable RSpec/ExpectActual\n  end\nend\n"
  },
  {
    "path": "spec/fixtures/selenium_driver_rspec_success.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\n\nRSpec.describe Capybara::Selenium::Driver do\n  it 'should exit with a zero exit status' do\n    options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }\n    browser = described_class.new(TestApp, **options).browser\n    expect(browser).to be_truthy\n    expect(true).to be(true) # rubocop:disable RSpec/ExpectActual,RSpec/IdenticalEqualityAssertion\n  end\nend\n"
  },
  {
    "path": "spec/minitest_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/minitest'\n\nclass MinitestTest < Minitest::Test\n  include Capybara::DSL\n  include Capybara::Minitest::Assertions\n\n  def setup\n    visit('/form')\n  end\n\n  def teardown\n    Capybara.reset_sessions!\n  end\n\n  def self.test_order\n    :sorted\n  end\n\n  def test_assert_text\n    assert_text('Form', normalize_ws: false)\n    assert_no_text('Not on the page')\n    refute_text('Also Not on the page')\n  end\n\n  def test_assert_title\n    visit('/with_title')\n    assert_title('Test Title')\n    assert_no_title('Not the title')\n    refute_title('Not the title')\n  end\n\n  def test_assert_current_path\n    assert_current_path('/form')\n    assert_current_path('/form') { |url| url.query.nil? }\n    assert_no_current_path('/not_form')\n    refute_current_path('/not_form')\n  end\n\n  def test_assert_xpath\n    assert_xpath('.//select[@id=\"form_title\"]')\n    assert_xpath('.//select', count: 1) { |el| el[:id] == 'form_title' }\n    assert_no_xpath('.//select[@id=\"not_form_title\"]')\n    assert_no_xpath('.//select') { |el| el[:id] == 'not_form_title' }\n    refute_xpath('.//select[@id=\"not_form_title\"]')\n  end\n\n  def test_assert_css\n    assert_css('select#form_title')\n    assert_no_css('select#not_form_title')\n  end\n\n  def test_assert_selector\n    assert_selector(:css, 'select#form_title')\n    assert_selector(:xpath, './/select[@id=\"form_title\"]')\n    assert_no_selector(:css, 'select#not_form_title')\n    assert_no_selector(:xpath, './/select[@id=\"not_form_title\"]')\n    refute_selector(:css, 'select#not_form_title')\n  end\n\n  def test_assert_element\n    visit('/with_html')\n    assert_element('a', text: 'A link')\n    assert_element(count: 1) { |el| el.text == 'A link' }\n    assert_no_element(text: 'Not on page')\n  end\n\n  def test_assert_link\n    visit('/with_html')\n    assert_link('A link')\n    assert_link(count: 1) { |el| el.text == 'A link' }\n    assert_no_link('Not on page')\n  end\n\n  def test_assert_button\n    assert_button('fresh_btn')\n    assert_button(count: 1) { |el| el[:id] == 'fresh_btn' }\n    assert_no_button('not_btn')\n  end\n\n  def test_assert_field\n    assert_field('customer_email')\n    assert_no_field('not_on_the_form')\n  end\n\n  def test_assert_select\n    assert_select('form_title')\n    assert_no_select('not_form_title')\n  end\n\n  def test_assert_checked_field\n    assert_checked_field('form_pets_dog')\n    assert_no_checked_field('form_pets_cat')\n    refute_checked_field('form_pets_snake')\n  end\n\n  def test_assert_unchecked_field\n    assert_unchecked_field('form_pets_cat')\n    assert_no_unchecked_field('form_pets_dog')\n    refute_unchecked_field('form_pets_snake')\n  end\n\n  def test_assert_table\n    visit('/tables')\n    assert_table('agent_table')\n    assert_no_table('not_on_form')\n    refute_table('not_on_form')\n  end\n\n  def test_assert_all_of_selectors\n    assert_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')\n  end\n\n  def test_assert_none_of_selectors\n    assert_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')\n  end\n\n  def test_assert_any_of_selectors\n    assert_any_of_selectors(:css, 'input#not_on_page', 'select#form_other_title')\n  end\n\n  def test_assert_matches_selector\n    assert_matches_selector(find(:field, 'customer_email'), :field, 'customer_email')\n    assert_not_matches_selector(find(:select, 'form_title'), :field, 'customer_email')\n    refute_matches_selector(find(:select, 'form_title'), :field, 'customer_email')\n  end\n\n  def test_assert_matches_css\n    assert_matches_css(find(:select, 'form_title'), 'select#form_title')\n    refute_matches_css(find(:select, 'form_title'), 'select#form_other_title')\n  end\n\n  def test_assert_matches_xpath\n    assert_matches_xpath(find(:select, 'form_title'), './/select[@id=\"form_title\"]')\n    refute_matches_xpath(find(:select, 'form_title'), './/select[@id=\"form_other_title\"]')\n  end\n\n  def test_assert_matches_style\n    skip \"Rack test doesn't support style\" if Capybara.current_driver == :rack_test\n    visit('/with_html')\n    assert_matches_style(find(:css, '#second'), display: 'inline')\n  end\n\n  def test_assert_ancestor\n    option = find(:option, 'Finnish')\n    assert_ancestor(option, :css, '#form_locale')\n  end\n\n  def test_assert_sibling\n    option = find(:css, '#form_title').find(:option, 'Mrs')\n    assert_sibling(option, :option, 'Mr')\n  end\nend\n\nRSpec.describe 'capybara/minitest' do\n  before do\n    Capybara.current_driver = :rack_test\n    Capybara.app = TestApp\n  end\n\n  after do\n    Capybara.use_default_driver\n  end\n\n  it 'should support minitest' do\n    output = StringIO.new\n    reporter = Minitest::SummaryReporter.new(output)\n    reporter.start\n    MinitestTest.run reporter, {}\n    reporter.report\n    expect(output.string).to include('23 runs, 56 assertions, 0 failures, 0 errors, 1 skips')\n  end\nend\n"
  },
  {
    "path": "spec/minitest_spec_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/minitest'\nrequire 'capybara/minitest/spec'\n\nclass MinitestSpecTest < Minitest::Spec\n  include ::Capybara::DSL\n  include ::Capybara::Minitest::Assertions\n\n  before do\n    visit('/form')\n  end\n\n  after do\n    Capybara.reset_sessions!\n  end\n\n  def self.test_order\n    :sorted\n  end\n\n  it 'supports text expectations' do\n    _(page).must_have_text('Form', minimum: 1)\n    _(page).wont_have_text('Not a form')\n    form = find(:css, 'form', text: 'Title')\n    _(form).must_have_text('Customer Email')\n    _(form).wont_have_text('Some other email')\n  end\n\n  it 'supports current_path expectations' do\n    _(page).must_have_current_path('/form')\n    _(page).wont_have_current_path('/form2')\n  end\n\n  it 'supports title expectations' do\n    visit('/with_title')\n    _(page).must_have_title('Test Title')\n    _(page).wont_have_title('Not the title')\n  end\n\n  it 'supports xpath expectations' do\n    _(page).must_have_xpath('.//input[@id=\"customer_email\"]')\n    _(page).wont_have_xpath('.//select[@id=\"not_form_title\"]')\n    _(page).wont_have_xpath('.//input[@id=\"customer_email\"]') { |el| el[:id] == 'not_customer_email' }\n    select = find(:select, 'form_title')\n    _(select).must_have_xpath('.//option[@class=\"title\"]')\n    _(select).must_have_xpath('.//option', count: 1) { |option| option[:class] != 'title' && !option.disabled? }\n    _(select).wont_have_xpath('.//input[@id=\"customer_email\"]')\n  end\n\n  it 'support css expectations' do\n    _(page).must_have_css('input#customer_email')\n    _(page).wont_have_css('select#not_form_title')\n    el = find(:select, 'form_title')\n    _(el).must_have_css('option.title')\n    _(el).wont_have_css('input#customer_email')\n  end\n\n  it 'supports link expectations' do\n    visit('/with_html')\n    _(page).must_have_link('A link')\n    _(page).wont_have_link('Not on page')\n  end\n\n  it 'supports button expectations' do\n    _(page).must_have_button('fresh_btn')\n    _(page).wont_have_button('not_btn')\n  end\n\n  it 'supports field expectations' do\n    _(page).must_have_field('customer_email')\n    _(page).wont_have_field('not_on_the_form')\n  end\n\n  it 'supports select expectations' do\n    _(page).must_have_select('form_title')\n    _(page).wont_have_select('not_form_title')\n  end\n\n  it 'supports checked_field expectations' do\n    _(page).must_have_checked_field('form_pets_dog')\n    _(page).wont_have_checked_field('form_pets_cat')\n  end\n\n  it 'supports unchecked_field expectations' do\n    _(page).must_have_unchecked_field('form_pets_cat')\n    _(page).wont_have_unchecked_field('form_pets_dog')\n  end\n\n  it 'supports table expectations' do\n    visit('/tables')\n    _(page).must_have_table('agent_table')\n    _(page).wont_have_table('not_on_form')\n  end\n\n  it 'supports all_of_selectors expectations' do\n    _(page).must_have_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')\n  end\n\n  it 'supports none_of_selectors expectations' do\n    _(page).must_have_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')\n  end\n\n  it 'supports any_of_selectors expectations' do\n    _(page).must_have_any_of_selectors(:css, 'select#form_other_title', 'input#not_on_page')\n  end\n\n  it 'supports match_selector expectations' do\n    _(find(:field, 'customer_email')).must_match_selector(:field, 'customer_email')\n    _(find(:select, 'form_title')).wont_match_selector(:field, 'customer_email')\n  end\n\n  it 'supports match_css expectations' do\n    _(find(:select, 'form_title')).must_match_css('select#form_title')\n    _(find(:select, 'form_title')).wont_match_css('select#form_other_title')\n  end\n\n  it 'supports match_xpath expectations' do\n    _(find(:select, 'form_title')).must_match_xpath('.//select[@id=\"form_title\"]')\n    _(find(:select, 'form_title')).wont_match_xpath('.//select[@id=\"not_on_page\"]')\n  end\n\n  it 'handles failures' do\n    _(page).must_have_select('non_existing_form_title')\n  end\n\n  it 'supports style expectations' do\n    skip \"Rack test doesn't support style\" if Capybara.current_driver == :rack_test\n    visit('/with_html')\n    _(find(:css, '#second')).must_have_style('display' => 'inline') # deprecated\n    _(find(:css, '#second')).must_match_style('display' => 'inline')\n  end\n\n  it 'supports ancestor expectations' do\n    option = find(:option, 'Finnish')\n    _(option).must_have_ancestor(:css, '#form_locale')\n  end\n\n  it 'supports sibling expectations' do\n    option = find(:css, '#form_title').find(:option, 'Mrs')\n    _(option).must_have_sibling(:option, 'Mr')\n  end\nend\n\nRSpec.describe 'capybara/minitest/spec' do\n  before do\n    Capybara.current_driver = :rack_test\n    Capybara.app = TestApp\n  end\n\n  after do\n    Capybara.use_default_driver\n  end\n\n  it 'should support minitest spec' do\n    output = StringIO.new\n    reporter = Minitest::SummaryReporter.new(output)\n    reporter.start\n    MinitestSpecTest.run reporter, {}\n    reporter.report\n    expect(output.string).to include('22 runs, 44 assertions, 1 failures, 0 errors, 1 skips')\n    # Make sure error messages are displayed\n    expect(output.string).to match(/expected to find select box \"non_existing_form_title\" .*but there were no matches/)\n  end\nend\n"
  },
  {
    "path": "spec/per_session_config_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/dsl'\n\nRSpec.describe Capybara::SessionConfig do\n  describe 'threadsafe' do\n    it 'defaults to global session options' do\n      Capybara.threadsafe = true\n      session = Capybara::Session.new(:rack_test, TestApp)\n      %i[default_host app_host always_include_port run_server\n         default_selector default_max_wait_time ignore_hidden_elements\n         automatic_reload match exact raise_server_errors visible_text_only\n         automatic_label_click enable_aria_label save_path\n         asset_host default_retry_interval].each do |m|\n           expect(session.config.public_send(m)).to eq Capybara.public_send(m)\n         end\n    end\n\n    it \"doesn't change global session when changed\" do\n      Capybara.threadsafe = true\n      host = 'http://my.example.com'\n      session = Capybara::Session.new(:rack_test, TestApp) do |config|\n        config.default_host = host\n        config.automatic_label_click = !config.automatic_label_click\n        config.server_errors << ArgumentError\n      end\n      expect(Capybara.default_host).not_to eq host\n      expect(session.config.default_host).to eq host\n      expect(Capybara.automatic_label_click).not_to eq session.config.automatic_label_click\n      expect(Capybara.server_errors).not_to eq session.config.server_errors\n    end\n\n    it \"doesn't allow session configuration block when false\" do\n      Capybara.threadsafe = false\n      expect do\n        Capybara::Session.new(:rack_test, TestApp) { |config| }\n      end.to raise_error 'A configuration block is only accepted when Capybara.threadsafe == true'\n    end\n\n    it \"doesn't allow session config when false\" do\n      Capybara.threadsafe = false\n      session = Capybara::Session.new(:rack_test, TestApp)\n      expect { session.config.default_selector = :title }.to raise_error(/Per session settings are only supported when Capybara.threadsafe == true/)\n      expect do\n        session.configure do |config|\n          config.exact = true\n        end\n      end.to raise_error(/Session configuration is only supported when Capybara.threadsafe == true/)\n    end\n\n    it 'uses the config from the session' do\n      Capybara.threadsafe = true\n      session = Capybara::Session.new(:rack_test, TestApp) do |config|\n        config.default_selector = :link\n      end\n      session.visit('/with_html')\n      expect(session.find('foo').tag_name).to eq 'a'\n    end\n\n    it \"won't change threadsafe once a session is created\" do\n      Capybara.threadsafe = true\n      Capybara.threadsafe = false\n      Capybara::Session.new(:rack_test, TestApp)\n      expect { Capybara.threadsafe = true }.to raise_error(/Threadsafe setting cannot be changed once a session is created/)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/rack_test_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule TestSessions\n  RackTest = Capybara::Session.new(:rack_test, TestApp)\nend\n\nskipped_tests = %i[\n  js\n  modals\n  screenshot\n  frames\n  windows\n  send_keys\n  server\n  hover\n  about_scheme\n  download\n  css\n  scroll\n  spatial\n  html_validation\n  shadow_dom\n  active_element\n]\nCapybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when /has_css\\? should support case insensitive :class and :id options/\n    skip \"Nokogiri doesn't support case insensitive CSS attribute matchers\"\n  when /#click_button should follow permanent redirects that maintain method/\n    skip \"Rack < 2 doesn't support 308\" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')\n  when /#attach_file with multipart form should send prior hidden field if no file submitted/\n    skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')\n  when /popover/\n    skip \"Rack-test driver doesn't support popover functionality\"\n  end\nend\n\nRSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes\n  include Capybara::RSpecMatchers\n\n  context 'with rack test driver' do\n    let(:session) { TestSessions::RackTest }\n\n    describe '#driver' do\n      it 'should be a rack test driver' do\n        expect(session.driver).to be_an_instance_of(Capybara::RackTest::Driver)\n      end\n    end\n\n    describe '#mode' do\n      it 'should remember the mode' do\n        expect(session.mode).to eq(:rack_test)\n      end\n    end\n\n    describe '#click_link' do\n      after do\n        session.driver.options[:respect_data_method] = false\n      end\n\n      it 'should use data-method if option is true' do\n        session.driver.options[:respect_data_method] = true\n        session.visit '/with_html'\n        session.click_link 'A link with data-method'\n        expect(session.html).to include('The requested object was deleted')\n      end\n\n      it 'should not use data-method if option is false' do\n        session.driver.options[:respect_data_method] = false\n        session.visit '/with_html'\n        session.click_link 'A link with data-method'\n        expect(session.html).to include('Not deleted')\n      end\n\n      it \"should use data-method if available even if it's capitalized\" do\n        session.driver.options[:respect_data_method] = true\n        session.visit '/with_html'\n        session.click_link 'A link with capitalized data-method'\n        expect(session.html).to include('The requested object was deleted')\n      end\n    end\n\n    describe '#fill_in' do\n      it 'should warn that :fill_options are not supported' do\n        session.visit '/with_html'\n        expect { session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true } }.to \\\n          output(/^Options passed to Node#set but the RackTest driver doesn't support any - ignoring/).to_stderr\n        expect(session).to have_field('test_field', with: 'not_monkey')\n      end\n    end\n\n    describe '#attach_file' do\n      context 'with multipart form' do\n        it 'should submit an empty form-data section if no file is submitted' do\n          session.visit('/form')\n          session.click_button('Upload Empty')\n          expect(session.html).to include('Successfully ignored empty file field.')\n        end\n\n        it 'should submit multipart even if no file is submitted' do\n          session.visit('/form')\n          session.click_button('Upload Empty')\n          expect(session.html).to include('Content type was multipart/form-data;')\n        end\n      end\n\n      it 'should not submit an obsolete mime type' do\n        test_jpg_file_path = File.expand_path('fixtures/capybara.csv', File.dirname(__FILE__))\n        session.visit('/form')\n        session.attach_file 'form_document', test_jpg_file_path\n        session.click_button('Upload Single')\n        expect(session).to have_content('Content-type: text/csv')\n      end\n    end\n\n    describe '#click' do\n      context 'on a label' do\n        it 'should toggle the associated checkbox' do\n          session.visit('/form')\n          expect(session).to have_unchecked_field('form_pets_cat')\n          session.find(:label, 'Cat').click\n          expect(session).to have_checked_field('form_pets_cat')\n          session.find(:label, 'Cat').click\n          expect(session).to have_unchecked_field('form_pets_cat')\n          session.find(:label, 'McLaren').click\n          expect(session).to have_checked_field('form_cars_mclaren', visible: :hidden)\n        end\n\n        it 'should toggle the associated radio' do\n          session.visit('/form')\n          expect(session).to have_unchecked_field('gender_male')\n          session.find(:label, 'Male').click\n          expect(session).to have_checked_field('gender_male')\n          session.find(:label, 'Female').click\n          expect(session).to have_unchecked_field('gender_male')\n        end\n\n        it 'should rewrite the forms action query for get submission' do\n          session.visit('/form')\n          session.click_button('mediocre')\n          expect(session).not_to have_current_path(/foo|bar/)\n        end\n\n        it 'should rewrite the submit buttons formaction query for get submission' do\n          session.visit('/form')\n          session.click_button('mediocre2')\n          expect(session).not_to have_current_path(/foo|bar/)\n        end\n      end\n    end\n\n    describe '#send_keys' do\n      it 'raises an UnsupportedMethodError' do\n        session.visit('/form')\n\n        expect { session.send_keys(:tab) }.to raise_error(Capybara::NotSupportedByDriverError)\n      end\n    end\n\n    describe '#active_element' do\n      it 'raises an UnsupportedMethodError' do\n        session.visit('/form')\n\n        expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)\n      end\n    end\n\n    describe '#text' do\n      it 'should return original text content for textareas' do\n        session.visit('/with_html')\n        session.find_field('normal', type: 'textarea', with: 'banana').set('hello')\n        normal = session.find(:css, '#normal')\n        expect(normal.value).to eq 'hello'\n        expect(normal.text).to eq 'banana'\n      end\n    end\n\n    describe '#style' do\n      it 'should raise an error' do\n        session.visit('/with_html')\n        el = session.find(:css, '#first')\n        expect { el.style('display') }.to raise_error NotImplementedError, /not process CSS/\n      end\n    end\n  end\nend\n\nRSpec.describe Capybara::RackTest::Driver do\n  let(:driver) { TestSessions::RackTest.driver }\n\n  describe ':headers option' do\n    it 'should always set headers' do\n      driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })\n      driver.visit('/get_header')\n      expect(driver.html).to include('foobar')\n    end\n\n    it 'should keep headers on link clicks' do\n      driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })\n      driver.visit('/header_links')\n      driver.find_xpath('.//a').first.click\n      expect(driver.html).to include('foobar')\n    end\n\n    it 'should keep headers on form submit' do\n      driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })\n      driver.visit('/header_links')\n      driver.find_xpath('.//input').first.click\n      expect(driver.html).to include('foobar')\n    end\n\n    it 'should keep headers on redirects' do\n      driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })\n      driver.visit('/get_header_via_redirect')\n      expect(driver.html).to include('foobar')\n    end\n  end\n\n  describe ':follow_redirects option' do\n    it 'defaults to following redirects' do\n      driver = described_class.new(TestApp)\n\n      driver.visit('/redirect')\n      expect(driver.response.headers['Location']).to be_nil\n      expect(driver.current_url).to match %r{/landed$}\n    end\n\n    it 'should not include fragments in the referer header' do\n      driver.visit('/header_links#an-anchor')\n      driver.find_xpath('.//input').first.click\n      expect(driver.request.get_header('HTTP_REFERER')).to eq('http://www.example.com/header_links')\n    end\n\n    it 'is possible to not follow redirects' do\n      driver = described_class.new(TestApp, follow_redirects: false)\n\n      driver.visit('/redirect')\n      expect(driver.response.headers['Location']).to match %r{/redirect_again$}\n      expect(driver.current_url).to match %r{/redirect$}\n    end\n  end\n\n  describe ':redirect_limit option' do\n    context 'with default redirect limit' do\n      let(:driver) { described_class.new(TestApp) }\n\n      it 'should follow 5 redirects' do\n        driver.visit('/redirect/5/times')\n        expect(driver.html).to include('redirection complete')\n      end\n\n      it 'should not follow more than 6 redirects' do\n        expect do\n          driver.visit('/redirect/6/times')\n        end.to raise_error(Capybara::InfiniteRedirectError)\n      end\n    end\n\n    context 'with 21 redirect limit' do\n      let(:driver) { described_class.new(TestApp, redirect_limit: 21) }\n\n      it 'should follow 21 redirects' do\n        driver.visit('/redirect/21/times')\n        expect(driver.html).to include('redirection complete')\n      end\n\n      it 'should not follow more than 21 redirects' do\n        expect do\n          driver.visit('/redirect/22/times')\n        end.to raise_error(Capybara::InfiniteRedirectError)\n      end\n    end\n  end\nend\n\nRSpec.describe 'Capybara::String' do\n  it 'should use HTML5 parsing' do\n    skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5\n    Capybara.use_html5_parsing = true\n    allow(Nokogiri::HTML5).to receive(:parse).and_call_original\n    Capybara.string('<div id=test_div></div>')\n    expect(Nokogiri::HTML5).to have_received(:parse)\n  end\nend\n\nmodule CSSHandlerIncludeTester\n  def dont_extend_css_handler\n    raise 'should never be called'\n  end\nend\n\nRSpec.describe Capybara::RackTest::CSSHandlers do\n  include CSSHandlerIncludeTester\n\n  it 'should not be extended by global includes' do\n    expect(described_class.new).not_to respond_to(:dont_extend_css_handler)\n  end\nend\n"
  },
  {
    "path": "spec/regexp_dissassembler_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Selector::RegexpDisassembler, :aggregate_failures do\n  it 'handles strings' do\n    verify_strings(\n      /abcdef/ => %w[abcdef],\n      /abc def/ => ['abc def']\n    )\n  end\n\n  it 'handles escaped characters' do\n    verify_strings(\n      /abc\\\\def/ => %w[abc\\def],\n      /abc\\.def/ => %w[abc.def],\n      /\\nabc/ => [\"\\nabc\"],\n      %r{abc/} => %w[abc/],\n      /ab\\++cd/ => %w[ab+ cd]\n    )\n  end\n\n  it 'handles wildcards' do\n    verify_strings(\n      /abc.*def/ => %w[abc def],\n      /.*def/ => %w[def],\n      /abc./ => %w[abc],\n      /abc.*/ => %w[abc],\n      /abc.def/ => %w[abc def],\n      /abc.def.ghi/ => %w[abc def ghi],\n      /abc.abcd.abcde/ => %w[abcde],\n      /.*/ => []\n    )\n  end\n\n  it 'ignores optional characters for substrings' do\n    {\n      /abc*def/ => %w[ab def],\n      /abc*/ => %w[ab],\n      /c*/ => [],\n      /abc?def/ => %w[ab def],\n      /abc?/ => %w[ab],\n      /abc?def?/ => %w[ab de],\n      /abc?def?g/ => %w[ab de g],\n      /d?/ => []\n    }.each do |regexp, expected|\n      expect(described_class.new(regexp).substrings).to eq expected\n    end\n  end\n\n  it 'handles optional characters for #alternated_substrings' do\n    verify_alternated_strings(\n      {\n        /abc*def/ => [%w[ab def]],\n        /abc*/ => [%w[ab]],\n        /c*/ => [],\n        /abc?def/ => [%w[abdef], %w[abcdef]],\n        /abc?/ => [%w[ab]],\n        /abc?def?/ => [%w[abde], %w[abcde]],\n        /abc?def?g/ => [%w[abdeg], %w[abdefg], %w[abcdeg], %w[abcdefg]],\n        /d?/ => []\n      }\n    )\n  end\n\n  it 'handles character classes' do\n    verify_strings(\n      /abc[a-z]/ => %w[abc],\n      /abc[a-z]def[0-9]g/ => %w[abc def g],\n      /[0-9]abc/ => %w[abc],\n      /[0-9]+/ => [],\n      /abc[0-9&&[^7]]/ => %w[abc]\n    )\n  end\n\n  it 'handles posix bracket expressions' do\n    verify_strings(\n      /abc[[:alpha:]]/ => %w[abc],\n      /[[:digit:]]abc/ => %w[abc],\n      /abc[[:print:]]def/ => %w[abc def]\n    )\n  end\n\n  it 'handles repitition' do\n    verify_strings(\n      /abc{3}/ => %w[abccc],\n      /abc{3}d/ => %w[abcccd],\n      /abc{0}/ => %w[ab],\n      /abc{,2}/ => %w[ab],\n      /abc{2,}/ => %w[abcc],\n      /def{1,5}/ => %w[def],\n      /abc+def/ => %w[abc def],\n      /ab(cde){,4}/ => %w[ab],\n      /(ab){,2}cd/ => %w[cd],\n      /(abc){2,3}/ => %w[abcabc],\n      /(abc){3}/ => %w[abcabcabc],\n      /ab{2,3}cd/ => %w[abb cd],\n      /(ab){2,3}cd/ => %w[abab cd]\n    )\n  end\n\n  it 'handles non-greedy repetition' do\n    verify_strings(\n      /abc.*?/ => %w[abc],\n      /abc+?/ => %w[abc],\n      /abc*?cde/ => %w[ab cde],\n      /(abc)+?def/ => %w[abc def],\n      /ab(cde)*?fg/ => %w[ab fg]\n    )\n  end\n\n  it 'ignores alternation for #substrings' do\n    {\n      /abc|def/ => [],\n      /ab(?:c|d)/ => %w[ab],\n      /ab(c|d|e)fg/ => %w[ab fg],\n      /ab?(c|d)fg/ => %w[a fg],\n      /ab(c|d)ef/ => %w[ab ef],\n      /ab(cd?|ef)g/ => %w[ab g],\n      /ab(cd|ef*)g/ => %w[ab g],\n      /ab|cd*/ => [],\n      /cd(?:ef|gh)|xyz/ => [],\n      /(cd(?:ef|gh)|xyz)/ => [],\n      /cd(ef|gh)+/ => %w[cd],\n      /cd(ef|gh)?/ => %w[cd],\n      /cd(ef|gh)?ij/ => %w[cd ij],\n      /cd(ef|gh)+ij/ => %w[cd ij],\n      /cd(ef|gh){2}ij/ => %w[cd ij],\n      /(cd(ef|g*))/ => %w[cd],\n      /ab(cd){0,2}ef/ => %w[ab ef],\n      /ab(cd){0,1}ef/ => %w[ab ef],\n      /ab(cd|cd)ef/ => %w[ab ef],\n      /ab(cd|cd)?ef/ => %w[ab ef],\n      /ab\\\\?cd/ => %w[ab cd]\n    }.each do |regexp, expected|\n      expect(described_class.new(regexp).substrings).to eq expected\n    end\n  end\n\n  it 'handles alternation for #alternated_substrings' do\n    verify_alternated_strings(\n      {\n        /abc|def/ => [%w[abc], %w[def]],\n        /ab(?:c|d)/ => [%w[abc], %w[abd]],\n        /ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]],\n        /ab?(c|d)fg/ => [%w[acfg], %w[adfg], %w[abcfg], %w[abdfg]],\n        /ab(c|d)ef/ => [%w[abcef], %w[abdef]],\n        /ab(cd?|ef)g/ => [%w[abcg], %w[abcdg], %w[abefg]],\n        /ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]],\n        /ab|cd*/ => [%w[ab], %w[c]],\n        /cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]],\n        /(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]],\n        /cd(ef|gh)+/ => [%w[cdef], %w[cdgh]],\n        /cd(ef|gh)?/ => [%w[cd]],\n        /cd(ef|gh)?ij/ => [%w[cdij], %w[cdefij], %w[cdghij]],\n        /cd(ef|gh)+ij/ => [%w[cdef ij], %w[cdgh ij]],\n        /cd(ef|gh){2}ij/ => [%w[cdefefij], %w[cdefghij], %w[cdghefij], %w[cdghghij]],\n        /(cd(ef|g*))/ => [%w[cd]],\n        /a|b*/ => [],\n        /ab(?:c|d?)/ => [%w[ab]],\n        /ab(c|d)|a*/ => [],\n        /(abc)?(d|e)/ => [%w[d], %w[e]],\n        /(abc*de)?(d|e)/ => [%w[d], %w[e]],\n        /(abc*de)?(d|e?)/ => [],\n        /(abc)?(d|e?)/ => [],\n        /ab(cd){0,2}ef/ => [%w[ab ef]],\n        /ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],\n        /ab(cd|cd)ef/ => [%w[abcdef]],\n        /ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],\n        /ab\\\\?cd/ => [%w[abcd], %w[ab\\cd]]\n      }\n    )\n  end\n\n  it 'handles grouping' do\n    verify_strings(\n      /(abc)/ => %w[abc],\n      /(abc)?/ => [],\n      /ab(cde)/ => %w[abcde],\n      /(abc)de/ => %w[abcde],\n      /ab(cde)fg/ => %w[abcdefg],\n      /ab(?<name>cd)ef/ => %w[abcdef],\n      /gh(?>ij)kl/ => %w[ghijkl],\n      /m(n.*p)q/ => %w[mn pq],\n      /(?:ab(cd)*){2,3}/ => %w[ab],\n      /(ab(cd){3})?/ => [],\n      /(ab(cd)+){2}/ => %w[abcd]\n    )\n  end\n\n  it 'handles meta characters' do\n    verify_strings(\n      /abc\\d/ => %w[abc],\n      /abc\\wdef/ => %w[abc def],\n      /\\habc/ => %w[abc]\n    )\n  end\n\n  it 'handles character properties' do\n    verify_strings(\n      /ab\\p{Alpha}cd/ => %w[ab cd],\n      /ab\\p{Blank}/ => %w[ab],\n      /\\p{Digit}cd/ => %w[cd]\n    )\n  end\n\n  it 'handles backreferences' do\n    verify_strings(\n      /a(?<group>abc).\\k<group>.+/ => %w[aabc]\n    )\n  end\n\n  it 'handles subexpressions' do\n    verify_strings(\n      /\\A(?<paren>a\\g<paren>*b)+\\z/ => %w[a b]\n    )\n  end\n\n  it 'ignores negative lookaheads' do\n    verify_strings(\n      /^(?!.*\\bContributing Editor\\b).*$/ => %w[],\n      /abc(?!.*def).*/ => %w[abc],\n      /(?!.*def)abc/ => %w[abc],\n      /abc(?!.*def.*).*ghi/ => %w[abc ghi],\n      /abc(?!.*bcd)def/ => %w[abcdef]\n    )\n  end\n\n  it 'handles anchors' do\n    verify_strings(\n      /^abc/ => %w[abc],\n      /def$/ => %w[def],\n      /^abc$/ => %w[abc]\n    )\n  end\n\n  def verify_strings(hsh)\n    hsh.each do |regexp, expected|\n      expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected\n    end\n    verify_alternated_strings(hsh, wrap: true)\n  end\n\n  def verify_alternated_strings(hsh, wrap: false)\n    hsh.each do |regexp, expected|\n      expected = [expected] if wrap && (expected != [])\n      expect(Capybara::Selector::RegexpDisassembler.new(regexp).alternated_substrings).to eq expected\n    end\n  end\nend\n"
  },
  {
    "path": "spec/result_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Result do\n  let :string do\n    Capybara.string <<-STRING\n      <ul>\n        <li>Alpha</li>\n        <li>Beta</li>\n        <li>Gamma</li>\n        <li>Delta</li>\n      </ul>\n    STRING\n  end\n\n  let :result do\n    string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet\n  end\n\n  it 'has a length' do\n    expect(result.length).to eq(4)\n  end\n\n  it 'has a first element' do\n    result.first.text == 'Alpha'\n  end\n\n  it 'has a last element' do\n    result.last.text == 'Delta'\n  end\n\n  it 'splats into multiple assignment' do\n    first, *rest, last = result\n\n    expect(first).to have_text 'Alpha'\n    expect(rest.first).to have_text 'Beta'\n    expect(rest.last).to have_text 'Gamma'\n    expect(last).to have_text 'Delta'\n  end\n\n  it 'can supports values_at method' do\n    expect(result.values_at(0, 2).map(&:text)).to eq(%w[Alpha Gamma])\n  end\n\n  it 'can return an element by its index' do\n    expect(result.at(1).text).to eq('Beta')\n    expect(result[2].text).to eq('Gamma')\n  end\n\n  it 'can be mapped' do\n    expect(result.map(&:text)).to eq(%w[Alpha Beta Gamma Delta])\n  end\n\n  it 'can be selected' do\n    expect(result.count do |element|\n      element.text.include? 't'\n    end).to eq(2)\n  end\n\n  it 'can be reduced' do\n    expect(result.reduce('') do |memo, element|\n      memo + element.text[0]\n    end).to eq('ABGD')\n  end\n\n  it 'can be sampled' do\n    expect(result).to include(result.sample)\n  end\n\n  it 'can be indexed' do\n    expect(result.index do |el|\n      el.text == 'Gamma'\n    end).to eq(2)\n  end\n\n  def recalc_result\n    string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet\n  end\n\n  it 'supports all modes of []' do\n    expect(recalc_result[1].text).to eq 'Beta'\n    expect(recalc_result[0, 2].map(&:text)).to eq %w[Alpha Beta]\n    expect(recalc_result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]\n    expect(recalc_result[-1].text).to eq 'Delta'\n    expect(recalc_result[-2, 3].map(&:text)).to eq %w[Gamma Delta]\n    expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]\n    expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]\n    expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]\n    expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta] # rubocop:disable Style/SlicingWithRange\n    expect(recalc_result[2..].map(&:text)).to eq %w[Gamma Delta]\n  end\n\n  it 'supports endless ranges' do\n    expect(result[2..].map(&:text)).to eq %w[Gamma Delta]\n  end\n\n  it 'supports inclusive positive beginless ranges' do\n    expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]\n  end\n\n  it 'supports inclusive negative beginless ranges' do\n    expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]\n    expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]\n  end\n\n  it 'supports exclusive positive beginless ranges' do\n    expect(result[...2].map(&:text)).to eq %w[Alpha Beta]\n  end\n\n  it 'supports exclusive negative beginless ranges' do\n    expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]\n    expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]\n  end\n\n  it 'works with filter blocks' do\n    result = string.all('//li') { |node| node.text == 'Alpha' }\n    expect(result.size).to eq 1\n  end\n\n  # Not a great test but it indirectly tests what is needed\n  it 'should evaluate filters lazily for idx' do\n    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n    # Not processed until accessed\n    expect(result.instance_variable_get(:@result_cache).size).to be 0\n\n    # Only one retrieved when needed\n    result.first\n    expect(result.instance_variable_get(:@result_cache).size).to be 1\n\n    # works for indexed access\n    result[0]\n    expect(result.instance_variable_get(:@result_cache).size).to be 1\n\n    result[2]\n    expect(result.instance_variable_get(:@result_cache).size).to be 3\n\n    # All cached when converted to array\n    result.to_a\n    expect(result.instance_variable_get(:@result_cache).size).to eq 4\n  end\n\n  it 'should evaluate filters lazily for range' do\n    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n    result[0..1]\n    expect(result.instance_variable_get(:@result_cache).size).to be 2\n\n    expect(result[0..7].size).to eq 4\n    expect(result.instance_variable_get(:@result_cache).size).to be 4\n  end\n\n  it 'should evaluate filters lazily for idx and length' do\n    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n    result[1, 2]\n    expect(result.instance_variable_get(:@result_cache).size).to be 3\n\n    expect(result[2, 5].size).to eq 2\n    expect(result.instance_variable_get(:@result_cache).size).to be 4\n  end\n\n  it 'should only need to evaluate one result for any?' do\n    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n    result.any?\n    expect(result.instance_variable_get(:@result_cache).size).to be 1\n  end\n\n  it 'should evaluate all elements when #to_a called' do\n    # All cached when converted to array\n    result.to_a\n    expect(result.instance_variable_get(:@result_cache).size).to eq 4\n  end\n\n  describe '#each' do\n    it 'lazily evaluates' do\n      skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n      results = []\n      result.each do |el|\n        results << el\n        expect(result.instance_variable_get(:@result_cache).size).to eq results.size\n      end\n\n      expect(results.size).to eq 4\n    end\n\n    context 'without a block' do\n      it 'returns an iterator' do\n        expect(result.each).to be_a(Enumerator)\n      end\n\n      it 'lazily evaluates' do\n        skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?\n        result.each.with_index do |_el, idx|\n          expect(result.instance_variable_get(:@result_cache).size).to eq(idx + 1) # 0 indexing\n        end\n      end\n    end\n  end\n\n  def jruby_lazy_enumerator_workaround?\n    RUBY_PLATFORM == 'java'\n  end\nend\n"
  },
  {
    "path": "spec/rspec/features_spec.rb",
    "content": "# frozen_string_literal: true\n\n# rubocop:disable RSpec/MultipleDescribes\n\nrequire 'spec_helper'\nrequire 'capybara/rspec'\n\n# rubocop:disable RSpec/InstanceVariable\nRSpec.configuration.before(:each, file_path: './spec/rspec/features_spec.rb') do\n  @in_filtered_hook = true\nend\n\nfeature \"Capybara's feature DSL\" do\n  background do\n    @in_background = true\n  end\n\n  scenario 'includes Capybara' do\n    visit('/')\n    expect(page).to have_content('Hello world!')\n  end\n\n  scenario 'preserves description' do |ex|\n    expect(ex.metadata[:full_description])\n      .to eq(\"Capybara's feature DSL preserves description\")\n  end\n\n  scenario 'allows driver switching', driver: :selenium do\n    expect(Capybara.current_driver).to eq(:selenium)\n  end\n\n  scenario 'runs background' do\n    expect(@in_background).to be_truthy\n  end\n\n  scenario 'runs hooks filtered by file path' do\n    expect(@in_filtered_hook).to be_truthy\n  end\n\n  scenario \"doesn't pollute the Object namespace\" do\n    expect(Object.new).not_to respond_to(:feature)\n  end\n\n  feature 'nested features' do\n    scenario 'work as expected' do\n      visit '/'\n      expect(page).to have_content 'Hello world!'\n    end\n\n    scenario 'are marked in the metadata as capybara_feature' do |ex|\n      expect(ex.metadata[:capybara_feature]).to be_truthy\n    end\n\n    scenario 'have a type of :feature' do |ex|\n      expect(ex.metadata[:type]).to eq :feature\n    end\n  end\nend\n# rubocop:enable RSpec/InstanceVariable\n\nfeature 'given and given! aliases to let and let!' do\n  given(:value) { :available }\n  given!(:value_in_background) { :available }\n\n  background do\n    expect(value_in_background).to be(:available)\n  end\n\n  scenario 'given and given! work as intended' do\n    expect(value).to be(:available)\n    expect(value_in_background).to be(:available)\n  end\nend\n\nfeature \"Capybara's feature DSL with driver\", driver: :culerity do\n  scenario 'switches driver' do\n    expect(Capybara.current_driver).to eq(:culerity)\n  end\nend\n\n# rubocop:disable RSpec/RepeatedExample\nxfeature 'if xfeature aliases to pending then' do\n  scenario \"this should be 'temporarily disabled with xfeature'\" do\n    # dummy\n  end\n\n  scenario \"this also should be 'temporarily disabled with xfeature'\" do\n    # dummy\n  end\nend\n\nffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus\n  scenario 'scenario inside this feature has metatag focus tag' do |example|\n    expect(example.metadata[:focus]).to be true\n  end\n\n  scenario 'other scenarios also has metatag focus tag' do |example|\n    expect(example.metadata[:focus]).to be true\n  end\nend\n# rubocop:enable RSpec/RepeatedExample, RSpec/MultipleDescribes\n"
  },
  {
    "path": "spec/rspec/scenarios_spec.rb",
    "content": "# frozen_string_literal: true\n\n# rubocop:disable RSpec/MultipleDescribes\n\nrequire 'spec_helper'\nrequire 'capybara/rspec'\n\nRSpec.configuration.before(:each, file_path: './spec/rspec/scenarios_spec.rb') do\n  @in_filtered_hook = true\nend\n\nfeature 'if fscenario aliases focused tag then' do\n  fscenario 'scenario should have focused meta tag' do |example| # rubocop:disable RSpec/Focus\n    expect(example.metadata[:focus]).to be true\n  end\nend\n\nfeature 'if xscenario aliases to pending then' do\n  xscenario \"this test should be 'temporarily disabled with xscenario'\" do # rubocop:disable RSpec/PendingWithoutReason\n  end\nend\n\n# rubocop:enable RSpec/MultipleDescribes\n"
  },
  {
    "path": "spec/rspec/shared_spec_matchers.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/dsl'\nrequire 'capybara/rspec/matchers'\nrequire 'benchmark'\n\n# rubocop:disable RSpec/ExpectActual\n\nRSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|\n  include Capybara::DSL\n  include Capybara::RSpecMatchers\n\n  describe 'have_css matcher' do\n    it 'gives proper description' do\n      expect(have_css('h1').description).to eq('have visible css \"h1\"')\n    end\n\n    context 'on a string' do\n      context 'with should' do\n        it 'passes if has_css? returns true' do\n          expect('<h1>Text</h1>').to have_css('h1')\n        end\n\n        it 'fails if has_css? returns false' do\n          expect do\n            expect('<h1>Text</h1>').to have_css('h2')\n          end.to raise_error(/expected to find css \"h2\" but there were no matches/)\n        end\n\n        it 'passes if matched node count equals expected count' do\n          expect('<h1>Text</h1>').to have_css('h1', count: 1)\n        end\n\n        it 'fails if matched node count does not equal expected count' do\n          expect do\n            expect('<h1>Text</h1>').to have_css('h1', count: 2)\n          end.to raise_error('expected to find visible css \"h1\" 2 times, found 1 match: \"Text\"')\n        end\n\n        it 'fails if matched node count is less than expected minimum count' do\n          expect do\n            expect('<h1>Text</h1>').to have_css('p', minimum: 1)\n          end.to raise_error('expected to find css \"p\" at least 1 time but there were no matches')\n        end\n\n        it 'fails if matched node count is more than expected maximum count' do\n          expect do\n            expect('<h1>Text</h1><h1>Text</h1><h1>Text</h1>').to have_css('h1', maximum: 2)\n          end.to raise_error('expected to find visible css \"h1\" at most 2 times, found 3 matches: \"Text\", \"Text\", \"Text\"')\n        end\n\n        it 'fails if matched node count does not belong to expected range' do\n          expect do\n            expect('<h1>Text</h1>').to have_css('h1', between: 2..3)\n          end.to raise_error('expected to find visible css \"h1\" between 2 and 3 times, found 1 match: \"Text\"')\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_css? returns true' do\n          expect('<h1>Text</h1>').not_to have_css('h2')\n        end\n\n        it 'fails if has_no_css? returns false' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_css('h1')\n          end.to raise_error(/expected not to find visible css \"h1\"/)\n        end\n\n        it 'passes if matched node count does not equal expected count' do\n          expect('<h1>Text</h1>').not_to have_css('h1', count: 2)\n        end\n\n        it 'fails if matched node count equals expected count' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_css('h1', count: 1)\n          end.to raise_error(/expected not to find visible css \"h1\"/)\n        end\n      end\n\n      it 'supports compounding' do\n        expect('<h1>Text</h1><h2>Text</h2>').to have_css('h1').and have_css('h2')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_css('h3').or have_css('h1')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_no_css('h4').and have_css('h2')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_no_css('h2').or have_css('h1')\n      end\n    end\n\n    context 'on a page or node' do\n      before do\n        session.visit('/with_html')\n      end\n\n      context 'with should' do\n        it 'passes if has_css? returns true' do\n          expect(session).to have_css('h1')\n        end\n\n        it 'fails if has_css? returns false' do\n          expect do\n            expect(session).to have_css('h1#doesnotexist')\n          end.to raise_error(/expected to find css \"h1#doesnotexist\" but there were no matches/)\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_css? returns true' do\n          expect(session).not_to have_css('h1#doesnotexist')\n        end\n\n        it 'fails if has_no_css? returns false' do\n          expect do\n            expect(session).not_to have_css('h1')\n          end.to raise_error(/expected not to find visible css \"h1\"/)\n        end\n      end\n    end\n  end\n\n  describe 'have_xpath matcher' do\n    it 'gives proper description' do\n      expect(have_xpath('//h1').description).to eq('have visible xpath \"//h1\"')\n    end\n\n    context 'on a string' do\n      context 'with should' do\n        it 'passes if has_xpath? returns true' do\n          expect('<h1>Text</h1>').to have_xpath('//h1')\n        end\n\n        it 'fails if has_xpath? returns false' do\n          expect do\n            expect('<h1>Text</h1>').to have_xpath('//h2')\n          end.to raise_error(%r{expected to find xpath \"//h2\" but there were no matches})\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_xpath? returns true' do\n          expect('<h1>Text</h1>').not_to have_xpath('//h2')\n        end\n\n        it 'fails if has_no_xpath? returns false' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_xpath('//h1')\n          end.to raise_error(%r{expected not to find visible xpath \"//h1\"})\n        end\n      end\n\n      it 'supports compounding' do\n        expect('<h1>Text</h1><h2>Text</h2>').to have_xpath('//h1').and have_xpath('//h2')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_xpath('//h3').or have_xpath('//h1')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_no_xpath('//h4').and have_xpath('//h1')\n        expect('<h1>Text</h1><h2>Text</h2>').to have_no_xpath('//h4').or have_xpath('//h4')\n      end\n    end\n\n    context 'on a page or node' do\n      before do\n        session.visit('/with_html')\n      end\n\n      context 'with should' do\n        it 'passes if has_xpath? returns true' do\n          expect(session).to have_xpath('//h1')\n        end\n\n        it 'fails if has_xpath? returns false' do\n          expect do\n            expect(session).to have_xpath(\"//h1[@id='doesnotexist']\")\n          end.to raise_error(%r{expected to find xpath \"//h1\\[@id='doesnotexist'\\]\" but there were no matches})\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_xpath? returns true' do\n          expect(session).not_to have_xpath('//h1[@id=\"doesnotexist\"]')\n        end\n\n        it 'fails if has_no_xpath? returns false' do\n          expect do\n            expect(session).not_to have_xpath('//h1')\n          end.to raise_error(%r{expected not to find visible xpath \"//h1\"})\n        end\n      end\n    end\n  end\n\n  describe 'have_selector matcher' do\n    it 'gives proper description' do\n      matcher = have_selector('//h1')\n      expect('<h1>Text</h1>').to matcher\n      expect(matcher.description).to eq('have visible xpath \"//h1\"')\n    end\n\n    context 'on a string' do\n      context 'with should' do\n        it 'passes if has_selector? returns true' do\n          expect('<h1>Text</h1>').to have_selector('//h1')\n        end\n\n        it 'fails if has_selector? returns false' do\n          expect do\n            expect('<h1>Text</h1>').to have_selector('//h2')\n          end.to raise_error(%r{expected to find xpath \"//h2\" but there were no matches})\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_selector? returns true' do\n          expect('<h1>Text</h1>').not_to have_selector(:css, 'h2')\n        end\n\n        it 'fails if has_no_selector? returns false' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_selector(:css, 'h1')\n          end.to raise_error(/expected not to find visible css \"h1\"/)\n        end\n      end\n    end\n\n    context 'on a page or node' do\n      before do\n        session.visit('/with_html')\n      end\n\n      context 'with should' do\n        it 'passes if has_selector? returns true' do\n          expect(session).to have_selector('//h1', text: 'test')\n        end\n\n        it 'fails if has_selector? returns false' do\n          expect do\n            expect(session).to have_selector(\"//h1[@id='doesnotexist']\")\n          end.to raise_error(%r{expected to find xpath \"//h1\\[@id='doesnotexist'\\]\" but there were no matches})\n        end\n\n        it 'includes text in error message' do\n          expect do\n            expect(session).to have_selector('//h1', text: 'wrong text')\n          end.to raise_error(%r{expected to find visible xpath \"//h1\" with text \"wrong text\" but there were no matches})\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_css? returns true' do\n          expect(session).not_to have_selector(:css, 'h1#doesnotexist')\n        end\n\n        it 'fails if has_no_selector? returns false' do\n          expect do\n            expect(session).not_to have_selector(:css, 'h1', text: 'test')\n          end.to raise_error(/expected not to find visible css \"h1\" with text \"test\"/)\n        end\n      end\n    end\n\n    it 'supports compounding' do\n      expect('<h1>Text</h1><h2>Text</h2>').to have_selector('//h1').and have_selector('//h2')\n      expect('<h1>Text</h1><h2>Text</h2>').to have_selector('//h3').or have_selector('//h1')\n      expect('<h1>Text</h1><h2>Text</h2>').to have_no_selector('//h3').and have_selector('//h1')\n    end\n  end\n\n  describe 'have_content matcher' do\n    it 'gives proper description' do\n      expect(have_content('Text').description).to eq('have text \"Text\"')\n    end\n\n    context 'on a string' do\n      context 'with should' do\n        it 'passes if has_content? returns true' do\n          expect('<h1>Text</h1>').to have_content('Text')\n        end\n\n        it 'passes if has_content? returns true using regexp' do\n          expect('<h1>Text</h1>').to have_content(/ext/)\n        end\n\n        it 'fails if has_content? returns false' do\n          expect do\n            expect('<h1>Text</h1>').to have_content('No such Text')\n          end.to raise_error(/expected to find text \"No such Text\" in \"Text\"/)\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_content? returns true' do\n          expect('<h1>Text</h1>').not_to have_content('No such Text')\n        end\n\n        it 'passes because escapes any characters that would have special meaning in a regexp' do\n          expect('<h1>Text</h1>').not_to have_content('.')\n        end\n\n        it 'fails if has_no_content? returns false' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_content('Text')\n          end.to raise_error(/expected not to find text \"Text\" in \"Text\"/)\n        end\n      end\n    end\n\n    context 'on a page or node' do\n      before do\n        session.visit('/with_html')\n      end\n\n      context 'with should' do\n        it 'passes if has_content? returns true' do\n          expect(session).to have_content('This is a test')\n        end\n\n        it 'passes if has_content? returns true using regexp' do\n          expect(session).to have_content(/test/)\n        end\n\n        it 'fails if has_content? returns false' do\n          expect do\n            expect(session).to have_content('No such Text')\n          end.to raise_error(/expected to find text \"No such Text\" in \"(.*)This is a test(.*)\"/)\n        end\n\n        context 'with default selector CSS' do\n          before { Capybara.default_selector = :css }\n\n          after { Capybara.default_selector = :xpath }\n\n          it 'fails if has_content? returns false' do\n            expect do\n              expect(session).to have_content('No such Text')\n            end.to raise_error(/expected to find text \"No such Text\" in \"(.*)This is a test(.*)\"/)\n          end\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_content? returns true' do\n          expect(session).not_to have_content('No such Text')\n        end\n\n        it 'fails if has_no_content? returns false' do\n          expect do\n            expect(session).not_to have_content('This is a test')\n          end.to raise_error(/expected not to find text \"This is a test\"/)\n        end\n\n        it 'not_to have_content behaves the same as to have_no_content' do\n          Capybara.using_wait_time(5) do\n            expect(session).to have_content('This is a test')\n            start = Time.now\n            expect(session).to have_no_content('No such Text')\n            to_time = Time.now\n            expect(session).not_to have_content('No such Text')\n            not_to_time = Time.now\n            expect(not_to_time - to_time).to be_within(0.5).of(to_time - start)\n          end\n        end\n      end\n    end\n\n    it 'supports compounding' do\n      expect('<h1>Text</h1><h2>And</h2>').to have_content('Text').and have_content('And')\n      expect('<h1>Text</h1><h2>Or</h2>').to have_content('XYZ').or have_content('Or')\n      expect('<h1>Text</h1><h2>Or</h2>').to have_no_content('XYZ').and have_content('Or')\n    end\n  end\n\n  describe 'have_text matcher' do\n    it 'gives proper description' do\n      expect(have_text('Text').description).to eq('have text \"Text\"')\n    end\n\n    context 'on a string' do\n      context 'with should' do\n        it 'passes if text contains given string' do\n          expect('<h1>Text</h1>').to have_text('Text')\n        end\n\n        it 'passes if text matches given regexp' do\n          expect('<h1>Text</h1>').to have_text(/ext/)\n        end\n\n        it \"fails if text doesn't contain given string\" do\n          expect do\n            expect('<h1>Text</h1>').to have_text('No such Text')\n          end.to raise_error(/expected to find text \"No such Text\" in \"Text\"/)\n        end\n\n        it \"fails if text doesn't match given regexp\" do\n          expect do\n            expect('<h1>Text</h1>').to have_text(/No such Text/)\n          end.to raise_error('expected to find text matching /No such Text/ in \"Text\"')\n        end\n\n        it 'casts Integer to string' do\n          expect do\n            expect('<h1>Text</h1>').to have_text(3)\n          end.to raise_error(/expected to find text \"3\" in \"Text\"/)\n        end\n\n        it 'fails if matched text count does not equal to expected count' do\n          expect do\n            expect('<h1>Text</h1>').to have_text('Text', count: 2)\n          end.to raise_error('expected to find text \"Text\" 2 times but found 1 time in \"Text\"')\n        end\n\n        it 'fails if matched text count is less than expected minimum count' do\n          expect do\n            expect('<h1>Text</h1>').to have_text('Lorem', minimum: 1)\n          end.to raise_error('expected to find text \"Lorem\" at least 1 time but found 0 times in \"Text\"')\n        end\n\n        it 'fails if matched text count is more than expected maximum count' do\n          expect do\n            expect('<h1>Text TextText</h1>').to have_text('Text', maximum: 2)\n          end.to raise_error('expected to find text \"Text\" at most 2 times but found 3 times in \"Text TextText\"')\n        end\n\n        it 'fails if matched text count does not belong to expected range' do\n          expect do\n            expect('<h1>Text</h1>').to have_text('Text', between: 2..3)\n          end.to raise_error('expected to find text \"Text\" between 2 and 3 times but found 1 time in \"Text\"')\n        end\n      end\n\n      context 'with should_not' do\n        it \"passes if text doesn't contain a string\" do\n          expect('<h1>Text</h1>').not_to have_text('No such Text')\n        end\n\n        it 'passes because escapes any characters that would have special meaning in a regexp' do\n          expect('<h1>Text</h1>').not_to have_text('.')\n        end\n\n        it 'fails if text contains a string' do\n          expect do\n            expect('<h1>Text</h1>').not_to have_text('Text')\n          end.to raise_error(/expected not to find text \"Text\" in \"Text\"/)\n        end\n      end\n    end\n\n    context 'on a page or node' do\n      before do\n        session.visit('/with_html')\n      end\n\n      context 'with should' do\n        it 'passes if has_text? returns true' do\n          expect(session).to have_text('This is a test')\n        end\n\n        it 'passes if has_text? returns true using regexp' do\n          expect(session).to have_text(/test/)\n        end\n\n        it 'can check for all text' do\n          expect(session).to have_text(:all, 'Some of this text is hidden!')\n        end\n\n        it 'can check for visible text' do\n          expect(session).to have_text(:visible, 'Some of this text is')\n          expect(session).not_to have_text(:visible, 'Some of this text is hidden!')\n        end\n\n        it 'fails if has_text? returns false' do\n          expect do\n            expect(session).to have_text('No such Text')\n          end.to raise_error(/expected to find text \"No such Text\" in \"(.*)This is a test(.*)\"/)\n        end\n\n        context 'with default selector CSS' do\n          before { Capybara.default_selector = :css }\n\n          after { Capybara.default_selector = :xpath }\n\n          it 'fails if has_text? returns false' do\n            expect do\n              expect(session).to have_text('No such Text')\n            end.to raise_error(/expected to find text \"No such Text\" in \"(.*)This is a test(.*)\"/)\n          end\n        end\n      end\n\n      context 'with should_not' do\n        it 'passes if has_no_text? returns true' do\n          expect(session).not_to have_text('No such Text')\n        end\n\n        it 'fails if has_no_text? returns false' do\n          expect do\n            expect(session).not_to have_text('This is a test')\n          end.to raise_error(/expected not to find text \"This is a test\"/)\n        end\n      end\n    end\n\n    it 'supports compounding' do\n      expect('<h1>Text</h1><h2>And</h2>').to have_text('Text').and have_text('And')\n      expect('<h1>Text</h1><h2>Or</h2>').to have_text('Not here').or have_text('Or')\n    end\n  end\n\n  describe 'have_element matcher' do\n    let(:html) { '<img src=\"/img.jpg\" alt=\"a JPEG\"><img src=\"/img.png\" alt=\"a PNG\">' }\n\n    it 'gives proper description' do\n      expect(have_element('img').description).to eq('have visible element \"img\"')\n    end\n\n    it 'passes if there is such a element' do\n      expect(html).to have_element('img', src: '/img.jpg')\n    end\n\n    it 'fails if there is no such element' do\n      expect do\n        expect(html).to have_element('photo')\n      end.to raise_error(/expected to find element \"photo\"/)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_element('img', alt: 'a JPEG').and have_element('img', src: '/img.png')\n      expect(html).to have_element('photo').or have_element('img', src: '/img.jpg')\n      expect(html).to have_no_element('photo').and have_element('img', alt: 'a PNG')\n    end\n  end\n\n  describe 'have_link matcher' do\n    let(:html) { '<a href=\"#\">Just a link</a><a href=\"#\">Another link</a>' }\n\n    it 'gives proper description' do\n      expect(have_link('Just a link').description).to eq('have visible link \"Just a link\"')\n    end\n\n    it 'passes if there is such a link' do\n      expect(html).to have_link('Just a link')\n    end\n\n    it 'fails if there is no such link' do\n      expect do\n        expect(html).to have_link('No such Link')\n      end.to raise_error(/expected to find link \"No such Link\"/)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_link('Just a link').and have_link('Another link')\n      expect(html).to have_link('Not a link').or have_link('Another link')\n      expect(html).to have_no_link('Not a link').and have_link('Another link')\n    end\n  end\n\n  describe 'have_title matcher' do\n    it 'gives proper description' do\n      expect(have_title('Just a title').description).to eq('have title \"Just a title\"')\n    end\n\n    context 'on a string' do\n      let(:html) { '<title>Just a title</title>' }\n\n      it 'passes if there is such a title' do\n        expect(html).to have_title('Just a title')\n      end\n\n      it 'fails if there is no such title' do\n        expect do\n          expect(html).to have_title('No such title')\n        end.to raise_error('expected \"Just a title\" to include \"No such title\"')\n      end\n\n      it \"fails if title doesn't match regexp\" do\n        expect do\n          expect(html).to have_title(/[[:upper:]]+[[:lower:]]+l{2}o/)\n        end.to raise_error('expected \"Just a title\" to match /[[:upper:]]+[[:lower:]]+l{2}o/')\n      end\n    end\n\n    context 'on a page or node' do\n      it 'passes if there is such a title' do\n        session.visit('/with_js')\n        expect(session).to have_title('with_js')\n      end\n\n      it 'fails if there is no such title' do\n        session.visit('/with_js')\n        expect do\n          expect(session).to have_title('No such title')\n        end.to raise_error(/ to include \"No such title\"/)\n      end\n\n      context 'with wait' do\n        before do\n          session.visit('/with_js')\n        end\n\n        it 'waits if wait time is more than timeout' do\n          session.click_link('Change title')\n          session.using_wait_time 0 do\n            expect(session).to have_title('changed title', wait: 2)\n          end\n        end\n\n        it \"doesn't wait if wait time is less than timeout\" do\n          session.click_link('Change title')\n          session.using_wait_time 3 do\n            expect(session).not_to have_title('changed title', wait: 0)\n          end\n        end\n      end\n    end\n\n    it 'supports compounding' do\n      expect('<title>I compound</title>').to have_title('I dont compound').or have_title('I compound')\n    end\n  end\n\n  describe 'have_current_path matcher' do\n    it 'gives proper description' do\n      expect(have_current_path('http://www.example.com').description).to eq('have current path \"http://www.example.com\"')\n    end\n\n    context 'on a page or node' do\n      it 'passes if there is such a current path' do\n        session.visit('/with_js')\n        expect(session).to have_current_path('/with_js')\n      end\n\n      it 'fails if there is no such current_path' do\n        visit('/with_js')\n        expect do\n          expect(session).to have_current_path('/not_with_js')\n        end.to raise_error(%r{to equal \"/not_with_js\"})\n      end\n\n      context 'with wait' do\n        before do\n          session.visit('/with_js')\n        end\n\n        it 'waits if wait time is more than timeout' do\n          session.click_link('Change page')\n          session.using_wait_time 0 do\n            expect(session).to have_current_path('/with_html', wait: 2)\n          end\n        end\n\n        it \"doesn't wait if wait time is less than timeout\" do\n          session.click_link('Change page')\n          session.using_wait_time 0 do\n            expect(session).not_to have_current_path('/with_html')\n          end\n        end\n      end\n    end\n\n    it 'supports compounding' do\n      session.visit('/with_html')\n      expect(session).to have_current_path('/not_with_html').or have_current_path('/with_html')\n    end\n  end\n\n  describe 'have_button matcher' do\n    let(:html) { '<button>A button</button><input type=\"submit\" value=\"Another button\"/>' }\n\n    it 'gives proper description with no options' do\n      expect(have_button('A button').description).to eq('have visible button \"A button\" that is not disabled')\n    end\n\n    it 'gives proper description with disabled :any option' do\n      expect(have_button('A button', disabled: :all).description).to eq('have visible button \"A button\"')\n    end\n\n    it 'passes if there is such a button' do\n      expect(html).to have_button('A button')\n    end\n\n    it 'fails if there is no such button' do\n      expect do\n        expect(html).to have_button('No such Button')\n      end.to raise_error(/expected to find button \"No such Button\"/)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_button('Not this button').or have_button('A button')\n    end\n  end\n\n  describe 'have_field matcher' do\n    let(:html) { '<p><label>Text field<input type=\"text\" value=\"some value\"/></label></p>' }\n\n    it 'gives proper description' do\n      expect(have_field('Text field').description).to eq('have visible field \"Text field\" that is not disabled')\n    end\n\n    it 'gives proper description for a given value' do\n      expect(have_field('Text field', with: 'some value').description).to eq('have visible field \"Text field\" that is not disabled with value \"some value\"')\n    end\n\n    it 'passes if there is such a field' do\n      expect(html).to have_field('Text field')\n    end\n\n    it 'passes if there is such a field with value' do\n      expect(html).to have_field('Text field', with: 'some value')\n    end\n\n    it 'fails if there is no such field' do\n      expect do\n        expect(html).to have_field('No such Field')\n      end.to raise_error(/expected to find field \"No such Field\"/)\n    end\n\n    it 'fails if there is such field but with false value' do\n      expect do\n        expect(html).to have_field('Text field', with: 'false value')\n      end.to raise_error(/expected to find visible field \"Text field\"/)\n    end\n\n    it 'treats a given value as a string' do\n      foo = Class.new do\n        def to_s\n          'some value'\n        end\n      end\n      expect(html).to have_field('Text field', with: foo.new)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_field('Not this one').or have_field('Text field')\n    end\n  end\n\n  describe 'have_checked_field matcher' do\n    let(:html) do\n      '<label>it is checked<input type=\"checkbox\" checked=\"checked\"/></label>\n      <label>unchecked field<input type=\"checkbox\"/></label>'\n    end\n\n    it 'gives proper description' do\n      expect(have_checked_field('it is checked').description).to eq('have visible field \"it is checked\" that is not disabled that is checked')\n    end\n\n    context 'with should' do\n      it 'passes if there is such a field and it is checked' do\n        expect(html).to have_checked_field('it is checked')\n      end\n\n      it 'fails if there is such a field but it is not checked' do\n        expect do\n          expect(html).to have_checked_field('unchecked field')\n        end.to raise_error(/expected to find visible field \"unchecked field\"/)\n      end\n\n      it 'fails if there is no such field' do\n        expect do\n          expect(html).to have_checked_field('no such field')\n        end.to raise_error(/expected to find field \"no such field\"/)\n      end\n    end\n\n    context 'with should not' do\n      it 'fails if there is such a field and it is checked' do\n        expect do\n          expect(html).not_to have_checked_field('it is checked')\n        end.to raise_error(/expected not to find visible field \"it is checked\"/)\n      end\n\n      it 'passes if there is such a field but it is not checked' do\n        expect(html).not_to have_checked_field('unchecked field')\n      end\n\n      it 'passes if there is no such field' do\n        expect(html).not_to have_checked_field('no such field')\n      end\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_checked_field('not this one').or have_checked_field('it is checked')\n    end\n  end\n\n  describe 'have_unchecked_field matcher' do\n    let(:html) do\n      '<label>it is checked<input type=\"checkbox\" checked=\"checked\"/></label>\n      <label>unchecked field<input type=\"checkbox\"/></label>'\n    end\n\n    it 'gives proper description' do\n      expect(have_unchecked_field('unchecked field').description).to eq('have visible field \"unchecked field\" that is not disabled that is not checked')\n    end\n\n    context 'with should' do\n      it 'passes if there is such a field and it is not checked' do\n        expect(html).to have_unchecked_field('unchecked field')\n      end\n\n      it 'fails if there is such a field but it is checked' do\n        expect do\n          expect(html).to have_unchecked_field('it is checked')\n        end.to raise_error(/expected to find visible field \"it is checked\"/)\n      end\n\n      it 'fails if there is no such field' do\n        expect do\n          expect(html).to have_unchecked_field('no such field')\n        end.to raise_error(/expected to find field \"no such field\"/)\n      end\n    end\n\n    context 'with should not' do\n      it 'fails if there is such a field and it is not checked' do\n        expect do\n          expect(html).not_to have_unchecked_field('unchecked field')\n        end.to raise_error(/expected not to find visible field \"unchecked field\"/)\n      end\n\n      it 'passes if there is such a field but it is checked' do\n        expect(html).not_to have_unchecked_field('it is checked')\n      end\n\n      it 'passes if there is no such field' do\n        expect(html).not_to have_unchecked_field('no such field')\n      end\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_unchecked_field('it is checked').or have_unchecked_field('unchecked field')\n    end\n  end\n\n  describe 'have_select matcher' do\n    let(:html) { '<label>Select Box<select></select></label>' }\n\n    it 'gives proper description' do\n      expect(have_select('Select Box').description).to eq('have visible select box \"Select Box\" that is not disabled')\n    end\n\n    it 'gives proper description for a given selected value' do\n      expect(have_select('Select Box', selected: 'some value').description).to eq('have visible select box \"Select Box\" that is not disabled with \"some value\" selected')\n    end\n\n    it 'passes if there is such a select' do\n      expect(html).to have_select('Select Box')\n    end\n\n    it 'fails if there is no such select' do\n      expect do\n        expect(html).to have_select('No such Select box')\n      end.to raise_error(/expected to find select box \"No such Select box\"/)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_select('Not this one').or have_select('Select Box')\n    end\n  end\n\n  describe 'have_table matcher' do\n    let(:html) { '<table><caption>Lovely table</caption></table>' }\n\n    it 'gives proper description' do\n      expect(have_table('Lovely table').description).to eq('have visible table \"Lovely table\"')\n      expect(have_table('Lovely table', caption: 'my caption').description).to eq('have visible table \"Lovely table\" with caption \"my caption\"')\n    end\n\n    it 'gives proper description when :visible option passed' do\n      expect(have_table('Lovely table', visible: true).description).to eq('have visible table \"Lovely table\"') # rubocop:disable Capybara/VisibilityMatcher\n      expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table \"Lovely table\"')\n      expect(have_table('Lovely table', visible: :all).description).to eq('have table \"Lovely table\"')\n      expect(have_table('Lovely table', visible: false).description).to eq('have table \"Lovely table\"') # rubocop:disable Capybara/VisibilityMatcher\n    end\n\n    it 'passes if there is such a table' do\n      expect(html).to have_table('Lovely table')\n    end\n\n    it 'fails if there is no such table' do\n      expect do\n        expect(html).to have_table('No such Table')\n      end.to raise_error(/expected to find table \"No such Table\"/)\n    end\n\n    it 'supports compounding' do\n      expect(html).to have_table('nope').or have_table('Lovely table')\n    end\n  end\n\n  context 'compounding timing' do\n    let(:session) { session }\n    let(:el) { session.find(:css, '#reload-me') }\n\n    before do\n      session.visit('/with_js')\n    end\n\n    describe '#and' do\n      it \"should run 'concurrently'\" do\n        session.using_wait_time(2) do\n          matcher = have_text('this is not there').and have_text('neither is this')\n          expect(Benchmark.realtime do\n            expect do\n              expect(el).to matcher\n            end.to raise_error RSpec::Expectations::ExpectationNotMetError\n          end).to be_between(2, 3)\n        end\n      end\n\n      it \"should run 'concurrently' and retry\" do\n        session.click_link('reload-link')\n        session.using_wait_time(2) do\n          expect(Benchmark.realtime do\n            expect do\n              expect(el).to have_text('waiting to be reloaded').and(have_text('has been reloaded'))\n            end.to raise_error RSpec::Expectations::ExpectationNotMetError, /expected to find text \"waiting to be reloaded\" in \"has been reloaded\"/\n          end).to be_between(2, 3)\n        end\n      end\n\n      it 'should ignore :wait options' do\n        session.using_wait_time(2) do\n          matcher = have_text('this is not there', wait: 5).and have_text('neither is this', wait: 6)\n          expect(Benchmark.realtime do\n            expect do\n              expect(el).to matcher\n            end.to raise_error RSpec::Expectations::ExpectationNotMetError\n          end).to be_between(2, 3)\n        end\n      end\n\n      it 'should work on the session' do\n        session.using_wait_time(2) do\n          session.click_link('reload-link')\n          expect(session).to have_selector(:css, 'h1', text: 'FooBar').and have_text('has been reloaded')\n        end\n      end\n    end\n\n    describe '#and_then' do\n      it 'should run sequentially' do\n        session.click_link('reload-link')\n        expect(el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')\n      end\n    end\n\n    describe '#or' do\n      it \"should run 'concurrently'\" do\n        session.using_wait_time(3) do\n          expect(Benchmark.realtime do\n            expect(el).to have_text('has been reloaded').or have_text('waiting to be reloaded')\n          end).to be < 1\n        end\n      end\n\n      it 'should retry' do\n        session.using_wait_time(3) do\n          expect(Benchmark.realtime do\n            expect do\n              expect(el).to have_text('has been reloaded').or have_text('random stuff')\n            end.to raise_error RSpec::Expectations::ExpectationNotMetError\n          end).to be > 3\n        end\n      end\n\n      it 'should ignore :wait options' do\n        session.using_wait_time(2) do\n          expect(Benchmark.realtime do\n            expect do\n              expect(el).to have_text('this is not there', wait: 10).or have_text('neither is this', wait: 15)\n            end.to raise_error RSpec::Expectations::ExpectationNotMetError\n          end).to be_between(2, 3)\n        end\n      end\n\n      it 'should work on the session' do\n        session.using_wait_time(2) do\n          session.click_link('reload-link')\n          expect(session).to have_selector(:css, 'h1', text: 'Not on the page').or have_text('has been reloaded')\n        end\n      end\n    end\n  end\nend\n# rubocop:enable RSpec/ExpectActual\n"
  },
  {
    "path": "spec/rspec/views_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe 'capybara/rspec', type: :view do\n  it 'allows matchers to be used on strings' do\n    html = %(<h1>Test header</h1>)\n    expect(html).to have_css('h1', text: 'Test header')\n  end\n\n  it \"doesn't include RSpecMatcherProxies\" do\n    expect(self.class.ancestors).not_to include(Capybara::RSpecMatcherProxies)\n  end\nend\n"
  },
  {
    "path": "spec/rspec_matchers_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe 'Capybara RSpec Matchers', type: :feature do\n  context 'after called on session' do\n    it 'HaveSelector should allow getting a description of the matcher' do\n      visit('/with_html')\n      matcher = have_selector(:css, 'h2.head', minimum: 3)\n      expect(page).to matcher\n      expect { matcher.description }.not_to raise_error\n    end\n\n    it 'HaveText should allow getting a description' do\n      visit('/with_html')\n      matcher = have_text('Lorem')\n      expect(page).to matcher\n      expect { matcher.description }.not_to raise_error\n    end\n\n    it 'should produce the same error for .to have_no_xxx and .not_to have_xxx' do\n      visit('/with_html')\n      not_to_msg = error_msg_for { expect(page).not_to have_selector(:css, '#referrer') }\n      have_no_msg = error_msg_for { expect(page).to have_no_selector(:css, '#referrer') }\n      expect(not_to_msg).to eq have_no_msg\n\n      not_to_msg = error_msg_for { expect(page).not_to have_text('This is a test') }\n      have_no_msg = error_msg_for { expect(page).to have_no_text('This is a test') }\n      expect(not_to_msg).to eq have_no_msg\n    end\n  end\n\n  context 'after called on element' do\n    it 'HaveSelector should allow getting a description' do\n      visit('/with_html')\n      el = find(:css, '#first')\n      matcher = have_selector(:css, 'a#foo')\n      expect(el).to matcher\n      expect { matcher.description }.not_to raise_error\n    end\n\n    it 'MatchSelector should allow getting a description' do\n      visit('/with_html')\n      el = find(:css, '#first')\n      matcher = match_selector(:css, '#first')\n      expect(el).to matcher\n      expect { matcher.description }.not_to raise_error\n    end\n\n    it 'HaveText should allow getting a description' do\n      visit('/with_html')\n      el = find(:css, '#first')\n      matcher = have_text('Lorem')\n      expect(el).to matcher\n      expect { matcher.description }.not_to raise_error\n    end\n  end\n\n  context 'with a filter block' do\n    it 'applies the filter' do\n      visit('/with_html')\n      expect(page).to have_selector(:css, 'input#test_field')\n\n      expect(page).to have_selector(:css, 'input', count: 1) { |input| input.value == 'monkey' }\n      expect(page).to have_selector(:css, 'input', count: 1) do |input|\n        input.value == 'monkey'\n      end\n      expect(page).to have_no_selector(:css, 'input#test_field') { |input| input.value == 'not a monkey' }\n      expect(page).to have_no_selector(:css, 'input#test_field') do |input|\n        input.value == 'not a monkey'\n      end\n\n      expect(page).not_to have_selector(:css, 'input#test_field') { |input| input.value == 'not a monkey' }\n      expect(page).not_to have_selector(:css, 'input#test_field') do |input|\n        input.value == 'not a monkey'\n      end\n      expect(page).not_to have_no_selector(:css, 'input', count: 1) { |input| input.value == 'monkey' }\n      expect(page).not_to have_no_selector(:css, 'input#test_field', count: 1) do |input|\n        input.value == 'monkey'\n      end\n    end\n  end\n\n  def error_msg_for(&block)\n    expect(&block).to(raise_error { |e| return e.message })\n  end\nend\n"
  },
  {
    "path": "spec/rspec_spec.rb",
    "content": "# frozen_string_literal: true\n\n# rubocop:disable RSpec/MultipleDescribes\n\nrequire 'spec_helper'\n\nRSpec.describe 'capybara/rspec' do\n  context 'Feature', type: :feature do\n    it 'should include Capybara in rspec' do\n      visit('/foo')\n      expect(page.body).to include('Another World')\n    end\n\n    it 'should include RSpec matcher proxies' do\n      expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies\n    end\n\n    context 'resetting session', order: :defined do\n      it 'sets a cookie in one example...' do\n        visit('/set_cookie')\n        expect(page.body).to include('Cookie set to test_cookie')\n      end\n\n      it '...then it is not available in the next' do\n        visit('/get_cookie')\n        expect(page.body).not_to include('test_cookie')\n      end\n    end\n\n    context 'setting the current driver', order: :defined do\n      it 'sets the current driver in one example...' do\n        Capybara.current_driver = :selenium\n      end\n\n      it '...then it has returned to the default in the next example' do\n        expect(Capybara.current_driver).to eq(:rack_test)\n      end\n    end\n\n    it 'switches to the javascript driver when giving it as metadata', :js do\n      expect(Capybara.current_driver).to eq(Capybara.javascript_driver)\n    end\n\n    it 'switches to the given driver when giving it as metadata', driver: :culerity do\n      expect(Capybara.current_driver).to eq(:culerity)\n    end\n\n    describe '#all' do\n      it 'allows access to the Capybara finder' do\n        visit('/with_html')\n        found = all(:css, 'h2') { |element| element[:class] == 'head' }\n        expect(found.size).to eq(5)\n      end\n\n      it 'allows access to the RSpec matcher' do\n        visit('/with_html')\n        strings = %w[test1 test2]\n        expect(strings).to all(be_a(String))\n      end\n    end\n\n    describe '#within' do\n      it 'allows access to the Capybara scoper' do\n        visit('/with_html')\n        expect do\n          within(:css, '#does_not_exist') { click_link 'Go to simple' }\n        end.to raise_error(Capybara::ElementNotFound)\n      end\n\n      it 'allows access to the RSpec matcher' do\n        visit('/with_html')\n        # This reads terribly, but must call #within\n        expect(find(:css, 'span.number').text.to_i).to within(1).of(41)\n      end\n    end\n  end\n\n  context 'Type: Other', type: :other do\n    context 'when RSpec::Matchers is included after Capybara::DSL' do\n      let(:test_class_instance) do\n        Class.new do\n          include Capybara::DSL\n          include RSpec::Matchers\n        end.new\n      end\n\n      describe '#all' do\n        it 'allows access to the Capybara finder' do\n          test_class_instance.visit('/with_html')\n          expect(test_class_instance.all(:css, 'h2.head').size).to eq(5)\n        end\n\n        it 'allows access to the RSpec matcher' do\n          test_class_instance.visit('/with_html')\n          strings = %w[test1 test2]\n          expect(strings).to test_class_instance.all(be_a(String))\n        end\n      end\n\n      describe '#within' do\n        it 'allows access to the Capybara scoper' do\n          test_class_instance.visit('/with_html')\n          expect do\n            test_class_instance.within(:css, '#does_not_exist') { test_class_instance.click_link 'Go to simple' }\n          end.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'allows access to the RSpec matcher' do\n          test_class_instance.visit('/with_html')\n          # This reads terribly, but must call #within\n          expect(test_class_instance.find(:css, 'span.number').text.to_i).to test_class_instance.within(1).of(41)\n        end\n      end\n\n      context 'when `match_when_negated` is not defined in a matcher' do\n        before do\n          RSpec::Matchers.define :only_match_matcher do |expected|\n            match do |actual|\n              !(actual ^ expected)\n            end\n          end\n        end\n\n        it 'can be called with `not_to`' do\n          # This test is for a bug in jruby where `super` isn't defined correctly - https://github.com/jruby/jruby/issues/4678\n          # Reported in https://github.com/teamcapybara/capybara/issues/2115\n          test_class_instance.instance_eval do\n            expect do\n              expect(true).not_to only_match_matcher(false) # rubocop:disable RSpec/ExpectActual\n            end.not_to raise_error\n          end\n        end\n      end\n    end\n\n    it 'should not include Capybara' do\n      expect { visit('/') }.to raise_error(NoMethodError)\n    end\n  end\nend\n\nfeature 'Feature DSL' do\n  scenario 'is pulled in' do\n    visit('/foo')\n    expect(page.body).to include('Another World')\n  end\nend\n\n# rubocop:enable RSpec/MultipleDescribes\n"
  },
  {
    "path": "spec/sauce_spec_chrome.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\n\nrequire 'sauce_whisk'\n# require 'shared_selenium_session'\n# require 'shared_selenium_node'\n# require 'rspec/shared_spec_matchers'\n\nCapybara.register_driver :sauce_chrome do |app|\n  options = {\n    selenium_version: '4.8.0',\n    platform: 'macOS 10.12',\n    browser_name: 'chrome',\n    version: '65.0',\n    name: 'Capybara test',\n    build: ENV.fetch('TRAVIS_REPO_SLUG', \"Ruby-RSpec-Selenium: Local-#{Time.now.to_i}\"),\n    username: ENV.fetch('SAUCE_USERNAME', nil),\n    access_key: ENV.fetch('SAUCE_ACCESS_KEY', nil)\n  }\n\n  options.delete(:browser_name)\n\n  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(options)\n  url = 'https://ondemand.saucelabs.com:443/wd/hub'\n\n  Capybara::Selenium::Driver.new(app,\n                                 browser: :remote, url: url,\n                                 capabilities: capabilities,\n                                 options: Selenium::WebDriver::Chrome::Options.new(args: ['']))\nend\n\nCHROME_REMOTE_DRIVER = :sauce_chrome\n\nmodule TestSessions\n  Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger download]\n\nCapybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|\nend\n"
  },
  {
    "path": "spec/selector_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara do\n  include Capybara::RSpecMatchers\n\n  describe 'Selectors' do\n    let :string do\n      described_class.string <<-STRING\n        <html>\n          <head>\n            <title>selectors</title>\n          </head>\n          <body>\n            <div class=\"aa\" id=\"page\">\n              <div class=\"bb\" id=\"content\">\n                <h1 class=\"aa\">Totally awesome</h1>\n                <p>Yes it is</p>\n              </div>\n              <p class=\"bb cc\">Some Content</p>\n              <p class=\"bb dd !mine\"></p>\n            </div>\n            <div id=\"#special\">\n            </div>\n            <div class=\"some random words\" id=\"random_words\">\n              Something\n            </div>\n            <input id=\"2checkbox\" class=\"2checkbox\" type=\"checkbox\"/>\n            <input type=\"radio\"/>\n            <label for=\"my_text_input\">My Text Input</label>\n            <input type=\"text\" name=\"form[my_text_input]\" placeholder=\"my text\" id=\"my_text_input\"/>\n            <input type=\"file\" id=\"file\" class=\".special file\"/>\n            <input type=\"hidden\" id=\"hidden_field\" value=\"this is hidden\"/>\n            <input type=\"submit\" value=\"click me\" title=\"submit button\"/>\n            <input type=\"button\" value=\"don't click me\" title=\"Other button 1\" style=\"line-height: 30px;\"/>\n            <a href=\"#\">link</a>\n            <fieldset></fieldset>\n            <select id=\"select\">\n              <option value=\"a\">A</option>\n              <option value=\"b\" disabled>B</option>\n              <option value=\"c\" selected>C</option>\n            </select>\n            <table>\n              <tr><td></td></tr>\n            </table>\n            <table id=\"rows\">\n              <tr>\n                <td>A</td><td>B</td><td>C</td>\n              </tr>\n              <tr>\n                <td>D</td><td>E</td><td>F</td>\n              </tr>\n            </table>\n            <table id=\"cols\">\n            <tbody>\n              <tr>\n                <td>A</td><td>D</td>\n              </tr>\n              <tr>\n                <td>B</td><td>E</td>\n              </tr>\n              <tr>\n                <td>C</td><td>F</td>\n              </tr>\n              </tbody>\n            </table>\n          </body>\n        </html>\n      STRING\n    end\n\n    before do\n      described_class.add_selector :custom_selector do\n        css { |css_class| \"div.#{css_class}\" }\n        node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }\n      end\n\n      described_class.add_selector :custom_css_selector do\n        css(:name, :other_name) do |selector, name: nil, **|\n          selector ||= ''\n          selector += \"[name='#{name}']\" if name\n          selector\n        end\n\n        expression_filter(:placeholder) do |expr, val|\n          expr + \"[placeholder='#{val}']\"\n        end\n\n        expression_filter(:value) do |expr, val|\n          expr + \"[value='#{val}']\"\n        end\n\n        expression_filter(:title) do |expr, val|\n          expr + \"[title='#{val}']\"\n        end\n      end\n\n      described_class.add_selector :custom_xpath_selector do\n        xpath(:valid1, :valid2) { |selector| selector }\n        match { |value| value == 'match_me' }\n      end\n    end\n\n    it 'supports `filter` as an alias for `node_filter`' do\n      expect do\n        described_class.add_selector :filter_alias_selector do\n          css { |_unused| 'div' }\n          filter(:something) { |_node, _value| true }\n        end\n      end.not_to raise_error\n    end\n\n    describe 'adding a selector' do\n      it 'can set default visibility' do\n        described_class.add_selector :hidden_field do\n          visible :hidden\n          css { |_sel| 'input[type=\"hidden\"]' }\n        end\n\n        expect(string).to have_no_css('input[type=\"hidden\"]') # rubocop:disable Capybara/SpecificMatcher\n        expect(string).to have_selector(:hidden_field)\n      end\n    end\n\n    describe 'modify_selector' do\n      it 'allows modifying a selector' do\n        el = string.find(:custom_selector, 'aa')\n        expect(el.tag_name).to eq 'div'\n        described_class.modify_selector :custom_selector do\n          css { |css_class| \"h1.#{css_class}\" }\n        end\n        el = string.find(:custom_selector, 'aa')\n        expect(el.tag_name).to eq 'h1'\n      end\n\n      it \"doesn't change existing filters\" do\n        described_class.modify_selector :custom_selector do\n          css { |css_class| \"p.#{css_class}\" }\n        end\n        expect(string).to have_selector(:custom_selector, 'bb', count: 1)\n        expect(string).to have_selector(:custom_selector, 'bb', not_empty: false, count: 1)\n        expect(string).to have_selector(:custom_selector, 'bb', not_empty: :all, count: 2)\n      end\n    end\n\n    describe '::[]' do\n      it 'can find a selector' do\n        expect(Capybara::Selector[:field]).not_to be_nil\n      end\n\n      it 'raises if no selector found' do\n        expect { Capybara::Selector[:no_exist] }.to raise_error(ArgumentError, /Unknown selector type/)\n      end\n    end\n\n    describe '::for' do\n      it 'finds selector that matches the locator' do\n        expect(Capybara::Selector.for('match_me').name).to eq :custom_xpath_selector\n      end\n\n      it 'returns nil if no match' do\n        expect(Capybara::Selector.for('nothing')).to be_nil\n      end\n    end\n\n    describe 'xpath' do\n      it 'uses filter names passed in' do\n        described_class.add_selector :test do\n          xpath(:something, :other) { |_locator| XPath.descendant }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:something, :other)\n      end\n\n      it 'gets filter names from block if none passed to xpath method' do\n        described_class.add_selector :test do\n          xpath { |_locator, valid3:, valid4: nil| \"#{valid3} #{valid4}\" }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:valid3, :valid4)\n      end\n\n      it 'ignores block parameters if names passed in' do\n        described_class.add_selector :test do\n          xpath(:valid1) { |_locator, valid3:, valid4: nil| \"#{valid3} #{valid4}\" }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:valid1)\n        expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)\n      end\n    end\n\n    describe 'css' do\n      it \"supports filters specified in 'css' definition\" do\n        expect(string).to have_selector(:custom_css_selector, 'input', name: 'form[my_text_input]')\n        expect(string).to have_no_selector(:custom_css_selector, 'input', name: 'form[not_my_text_input]')\n      end\n\n      it 'supports explicitly defined expression filters' do\n        expect(string).to have_selector(:custom_css_selector, placeholder: 'my text')\n        expect(string).to have_no_selector(:custom_css_selector, placeholder: 'not my text')\n        expect(string).to have_selector(:custom_css_selector, value: 'click me', title: 'submit button')\n      end\n\n      it 'uses filter names passed in' do\n        described_class.add_selector :test do\n          css(:name, :other_name) { |_locator| '' }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:name, :other_name)\n      end\n\n      it 'gets filter names from block if none passed to css method' do\n        described_class.add_selector :test do\n          css { |_locator, valid3:, valid4: nil| \"#{valid3} #{valid4}\" }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:valid3, :valid4)\n      end\n\n      it 'ignores block parameters if names passed in' do\n        described_class.add_selector :test do\n          css(:valid1) { |_locator, valid3:, valid4: nil| \"#{valid3} #{valid4}\" }\n        end\n        selector = Capybara::Selector.new :test, config: nil, format: nil\n\n        expect(selector.expression_filters.keys).to include(:valid1)\n        expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)\n      end\n    end\n\n    describe 'builtin selectors' do\n      context 'when locator is nil' do\n        it 'devolves to just finding element types' do\n          selectors = {\n            field: \".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]\",\n            fieldset: './/fieldset',\n            link: './/a[./@href]',\n            link_or_button: \".//a[./@href] | .//input[./@type = 'submit' or ./@type = 'reset' or ./@type = 'image' or ./@type = 'button'] | .//button\",\n            fillable_field: \".//*[self::input | self::textarea][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'radio' or ./@type = 'checkbox' or ./@type = 'hidden' or ./@type = 'file')]\",\n            radio_button: \".//input[./@type = 'radio']\",\n            checkbox: \".//input[./@type = 'checkbox']\",\n            select: './/select',\n            option: './/option',\n            file_field: \".//input[./@type = 'file']\",\n            table: './/table'\n          }\n          selectors.each do |selector, xpath|\n            results = string.all(selector, nil).to_a.map(&:native)\n            expect(results.size).to be > 0\n            expect(results).to eq string.all(:xpath, xpath).to_a.map(&:native)\n          end\n        end\n      end\n\n      context 'with :id option' do\n        it 'works with compound css selectors' do\n          expect(string.all(:custom_css_selector, 'div, h1', id: 'page').size).to eq 1\n          expect(string.all(:custom_css_selector, 'h1, div', id: 'page').size).to eq 1\n        end\n\n        it \"works with 'special' characters\" do\n          expect(string.find(:custom_css_selector, 'div', id: '#special')[:id]).to eq '#special'\n          expect(string.find(:custom_css_selector, 'input', id: '2checkbox')[:id]).to eq '2checkbox'\n        end\n\n        it 'accepts XPath expression for xpath based selectors' do\n          expect(string.find(:custom_xpath_selector, './/div', id: XPath.contains('peci'))[:id]).to eq '#special'\n          expect(string.find(:custom_xpath_selector, './/input', id: XPath.ends_with('box'))[:id]).to eq '2checkbox'\n        end\n\n        it 'errors XPath expression for CSS based selectors' do\n          expect { string.find(:custom_css_selector, 'div', id: XPath.contains('peci')) }\n            .to raise_error(ArgumentError, /not supported/)\n        end\n\n        it 'accepts Regexp for xpath based selectors' do\n          expect(string.find(:custom_xpath_selector, './/div', id: /peci/)[:id]).to eq '#special'\n          expect(string.find(:custom_xpath_selector, './/div', id: /pEcI/i)[:id]).to eq '#special'\n        end\n\n        it 'accepts Regexp for css based selectors' do\n          expect(string.find(:custom_css_selector, 'div', id: /sp.*al/)[:id]).to eq '#special'\n        end\n      end\n\n      context 'with :class option' do\n        it 'works with compound css selectors' do\n          expect(string.all(:custom_css_selector, 'div, h1', class: 'aa').size).to eq 2\n          expect(string.all(:custom_css_selector, 'h1, div', class: 'aa').size).to eq 2\n        end\n\n        it 'handles negated classes' do\n          expect(string.all(:custom_css_selector, 'div, p', class: ['bb', '!cc']).size).to eq 2\n          expect(string.all(:custom_css_selector, 'div, p', class: ['!cc', '!dd', 'bb']).size).to eq 1\n          expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['bb', '!cc']).size).to eq 2\n          expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!cc', '!dd', 'bb']).size).to eq 1\n        end\n\n        it 'handles classes starting with ! by requiring negated negated first' do\n          expect(string.all(:custom_css_selector, 'div, p', class: ['!!!mine']).size).to eq 1\n          expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!!!mine']).size).to eq 1\n        end\n\n        it \"works with 'special' characters\" do\n          expect(string.find(:custom_css_selector, 'input', class: '.special')[:id]).to eq 'file'\n          expect(string.find(:custom_css_selector, 'input', class: '2checkbox')[:id]).to eq '2checkbox'\n        end\n\n        it 'accepts XPath expression for xpath based selectors' do\n          expect(string.find(:custom_xpath_selector, './/div', class: XPath.contains('dom wor'))[:id]).to eq 'random_words'\n          expect(string.find(:custom_xpath_selector, './/div', class: XPath.ends_with('words'))[:id]).to eq 'random_words'\n        end\n\n        it 'errors XPath expression for CSS based selectors' do\n          expect { string.find(:custom_css_selector, 'div', class: XPath.contains('random')) }\n            .to raise_error(ArgumentError, /not supported/)\n        end\n\n        it 'accepts Regexp for XPath based selectors' do\n          expect(string.find(:custom_xpath_selector, './/div', class: /dom wor/)[:id]).to eq 'random_words'\n          expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'\n        end\n\n        it 'accepts Regexp for CSS based selectors' do\n          expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'\n        end\n\n        it 'accepts Regexp for individual class names for XPath based selectors' do\n          expect(string.find(:custom_xpath_selector, './/div', class: [/random/, 'some'])[:id]).to eq 'random_words'\n          expect(string.find(:custom_xpath_selector, './/div', class: [/om/, /wor/])[:id]).to eq 'random_words'\n          expect { string.find(:custom_xpath_selector, './/div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)\n          expect { string.find(:custom_xpath_selector, './/div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)\n        end\n\n        it 'accepts Regexp for individual class names for CSS based selectors' do\n          expect(string.find(:custom_css_selector, 'div', class: [/random/])[:id]).to eq 'random_words'\n          expect(string.find(:custom_css_selector, 'div', class: [/om/, /wor/, 'some'])[:id]).to eq 'random_words'\n          expect { string.find(:custom_css_selector, 'div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)\n          expect { string.find(:custom_css_selector, 'div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)\n        end\n      end\n\n      context 'with :style option' do\n        it 'accepts string for CSS based selectors' do\n          expect(string.find(:custom_css_selector, 'input', style: 'line-height: 30px;')[:title]).to eq 'Other button 1'\n        end\n\n        it 'accepts Regexp for CSS base selectors' do\n          expect(string.find(:custom_css_selector, 'input', style: /30px/)[:title]).to eq 'Other button 1'\n        end\n      end\n\n      # :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,\n      # :option, :file_field, :label, :table, :frame\n\n      describe ':css selector' do\n        it 'finds by CSS locator' do\n          expect(string.find(:css, 'input#my_text_input')[:name]).to eq 'form[my_text_input]'\n        end\n      end\n\n      describe ':xpath selector' do\n        it 'finds by XPath locator' do\n          expect(string.find(:xpath, './/input[@id=\"my_text_input\"]')[:name]).to eq 'form[my_text_input]'\n        end\n      end\n\n      describe ':id selector' do\n        it 'finds by locator' do\n          expect(string.find(:id, 'my_text_input')[:name]).to eq 'form[my_text_input]'\n          expect(string.find(:id, /my_text_input/)[:name]).to eq 'form[my_text_input]'\n          expect(string.find(:id, /_text_/)[:name]).to eq 'form[my_text_input]'\n          expect(string.find(:id, /i[nmo]/)[:name]).to eq 'form[my_text_input]'\n        end\n      end\n\n      describe ':field selector' do\n        it 'finds by locator' do\n          expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'\n          expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'\n          expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'\n        end\n\n        it 'finds by id string' do\n          expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'\n        end\n\n        it 'finds by id regexp' do\n          expect(string.find(:field, id: /my_text_inp/)[:name]).to eq 'form[my_text_input]'\n        end\n\n        it 'finds by name' do\n          expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'\n        end\n\n        it 'finds by placeholder' do\n          expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'\n        end\n\n        it 'finds by type' do\n          expect(string.find(:field, type: 'file')[:id]).to eq 'file'\n          expect(string.find(:field, type: 'select')[:id]).to eq 'select'\n        end\n      end\n\n      describe ':option selector' do\n        it 'finds disabled options' do\n          expect(string.find(:option, disabled: true).value).to eq 'b'\n        end\n\n        it 'finds selected options' do\n          expect(string.find(:option, selected: true).value).to eq 'c'\n        end\n\n        it 'finds not selected and not disabled options' do\n          expect(string.find(:option, disabled: false, selected: false).value).to eq 'a'\n        end\n      end\n\n      describe ':button selector' do\n        it 'finds by value' do\n          expect(string.find(:button, 'click me').value).to eq 'click me'\n        end\n\n        it 'finds by title' do\n          expect(string.find(:button, 'submit button').value).to eq 'click me'\n        end\n\n        it 'includes non-matching parameters in failure message' do\n          expect { string.find(:button, 'click me', title: 'click me') }.to raise_error(/with title click me/)\n        end\n      end\n\n      describe ':element selector' do\n        it 'finds by any attributes' do\n          expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'\n        end\n\n        it 'supports regexp matching' do\n          expect(string.find(:element, 'input', type: /sub/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /sub\\w.*button/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /sub.* b.*ton/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /sub.*mit.*/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /^submit button$/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /^(?:submit|other) button$/).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /SuB.*mIt/i).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /^Su.*Bm.*It/i).value).to eq 'click me'\n          expect(string.find(:element, 'input', title: /^Ot.*he.*r b.*\\d/i).value).to eq \"don't click me\"\n        end\n\n        it 'still works with system keys' do\n          expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error\n        end\n\n        it 'works without element type' do\n          expect(string.find(:element, type: 'submit').value).to eq 'click me'\n        end\n\n        it 'validates attribute presence when true' do\n          expect(string.find(:element, name: true)[:id]).to eq 'my_text_input'\n        end\n\n        it 'validates attribute absence when false' do\n          expect(string.find(:element, 'option', disabled: false, selected: false).value).to eq 'a'\n        end\n\n        it 'includes wildcarded keys in description' do\n          expect { string.all(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }\n            .to(raise_error do |e|\n              expect(e).to be_a(Capybara::ElementNotFound)\n              expect(e.message).to include 'not_there => bad'\n              expect(e.message).to include 'with presence attribute'\n              expect(e.message).to include 'without absence attribute'\n              expect(e.message).not_to include 'count 1'\n            end)\n        end\n\n        it 'accepts XPath::Expression' do\n          expect(string.find(:element, 'input', type: XPath.starts_with('subm')).value).to eq 'click me'\n          expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'\n          expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'\n          expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'\n          expect(string.find(:element, 'input', title: XPath.contains_word('button 1'))[:type]).to eq 'button'\n        end\n      end\n\n      describe ':link_or_button selector' do\n        around do |example|\n          described_class.modify_selector(:link_or_button) do\n            expression_filter(:random) { |xpath, _| xpath } # do nothing filter\n          end\n          example.run\n          Capybara::Selector[:link_or_button].expression_filters.delete(:random)\n        end\n\n        it 'should not find links when disabled == true' do\n          expect(string.all(:link_or_button, disabled: true).size).to eq 0\n        end\n\n        context 'when modified' do\n          it 'should still work' do\n            filter = Capybara::Selector[:link_or_button].expression_filters[:random]\n            allow(filter).to receive(:apply_filter).and_call_original\n\n            expect(string.find(:link_or_button, 'click me', random: 'blah').value).to eq 'click me'\n            expect(filter).to have_received(:apply_filter).with(anything, :random, 'blah', anything)\n          end\n        end\n      end\n\n      describe ':table selector' do\n        it 'finds by rows' do\n          expect(string.find(:table, with_rows: [%w[D E F]])[:id]).to eq 'rows'\n        end\n\n        it 'finds by columns' do\n          expect(string.find(:table, with_cols: [%w[A B C]])[:id]).to eq 'cols'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_chrome.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\nCHROME_DRIVER = :selenium_chrome\n\nSelenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV.fetch('CI', nil) && ENV.fetch('CHROME_BETA', nil)\n\nSelenium::WebDriver.logger.ignore(:selenium_manager)\n\nbrowser_options = if ENV['HEADLESS']\n  Selenium::WebDriver::Options.chrome(args: ['--headless=new'])\nelse\n  Selenium::WebDriver::Options.chrome\nend\n\n# Chromedriver 77 requires setting this for headless mode on linux\n# Different versions of Chrome/selenium-webdriver require setting differently - jus set them all\nbrowser_options.add_preference('download.default_directory', Capybara.save_path)\nbrowser_options.add_preference(:download, default_directory: Capybara.save_path)\n\nCapybara.register_driver :selenium_chrome do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  driver_options = { browser: :chrome, timeout: 30 }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|\n    # Set download dir for Chrome < 77\n    driver.browser.download_path = Capybara.save_path\n  end\nend\n\nCapybara.register_driver :selenium_chrome_not_clear_storage do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  chrome_options = { browser: :chrome, clear_local_storage: false, clear_session_storage: false }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **chrome_options)\nend\n\nCapybara.register_driver :selenium_chrome_not_clear_session_storage do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  chrome_options = { browser: :chrome, clear_session_storage: false }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **chrome_options)\nend\n\nCapybara.register_driver :selenium_chrome_not_clear_local_storage do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  chrome_options = { browser: :chrome, clear_local_storage: false }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n  Capybara::Selenium::Driver.new(app, **chrome_options)\nend\n\nCapybara.register_driver :selenium_driver_subclass_with_chrome do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  subclass = Class.new(Capybara::Selenium::Driver)\n  chrome_options = { browser: :chrome, timeout: 30 }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  subclass.new(app, **chrome_options)\nend\n\nmodule TestSessions\n  Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger]\n\nCapybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Chrome) if ENV['CI']\n\nCapybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when /#click_link can download a file$/\n    skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?\n  when /Capybara::Session selenium_chrome node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  when /Capybara::Session selenium_chrome node #shadow_root/\n    skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)\n  end\nend\n\nRSpec.describe 'Capybara::Session with chrome' do\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::Chrome, CHROME_DRIVER\n  end\n\n  context 'storage' do\n    describe '#reset!' do\n      it 'clears storage by default' do\n        session = TestSessions::Chrome\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty\n      end\n\n      it 'does not clear storage when false' do\n        session = Capybara::Session.new(:selenium_chrome_not_clear_storage, TestApp)\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty\n      end\n\n      it 'can not clear session storage' do\n        session = Capybara::Session.new(:selenium_chrome_not_clear_session_storage, TestApp)\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty\n      end\n\n      it 'can not clear local storage' do\n        session = Capybara::Session.new(:selenium_chrome_not_clear_local_storage, TestApp)\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty\n      end\n    end\n  end\n\n  context 'timeout' do\n    it 'sets the http client read timeout' do\n      expect(TestSessions::Chrome.driver.browser.send(:bridge).http.read_timeout).to eq 30\n    end\n  end\n\n  describe 'filling in Chrome-specific date and time fields with keystrokes' do\n    let(:datetime) { Time.new(1983, 6, 19, 6, 30) }\n    let(:session) { TestSessions::Chrome }\n\n    before do\n      session.visit('/form')\n    end\n\n    it 'should fill in a date input with a String' do\n      session.fill_in('form_date', with: '06/19/1983')\n      session.click_button('awesome')\n      expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date\n    end\n\n    it 'should fill in a time input with a String' do\n      session.fill_in('form_time', with: '06:30A')\n      session.click_button('awesome')\n      results = extract_results(session)['time']\n      expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')\n    end\n\n    it 'should fill in a datetime input with a String' do\n      session.fill_in('form_datetime', with: \"06/19/1983\\t06:30A\")\n      session.click_button('awesome')\n      expect(Time.parse(extract_results(session)['datetime'])).to eq datetime\n    end\n  end\n\n  describe 'using subclass of selenium driver' do\n    it 'works' do\n      session = Capybara::Session.new(:selenium_driver_subclass_with_chrome, TestApp)\n      session.visit('/form')\n      expect(session).to have_current_path('/form')\n    end\n  end\n\n  describe 'log access' do\n    let(:logs) do\n      session.driver.browser.then do |chrome_driver|\n        chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage\n      end.logs\n    end\n\n    it 'does not error getting log types' do\n      expect do\n        logs.available_types\n      end.not_to raise_error\n    end\n\n    it 'does not error when getting logs' do\n      expect do\n        logs.get(:browser)\n      end.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_chrome_remote.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\ndef selenium_host\n  ENV.fetch('SELENIUM_HOST', '0.0.0.0')\nend\n\ndef selenium_port\n  ENV.fetch('SELENIUM_PORT', 4444)\nend\n\ndef ensure_selenium_running!\n  timer = Capybara::Helpers.timer(expire_in: 20)\n  begin\n    TCPSocket.open(selenium_host, selenium_port)\n  rescue StandardError\n    if timer.expired?\n      raise 'Selenium is not running. ' \\\n            \"You can run a selenium server easily with: \\n  \" \\\n            '$ docker-compose up -d selenium_chrome'\n    else\n      puts 'Waiting for Selenium docker instance...'\n      sleep 1\n      retry\n    end\n  end\nend\n\ndef selenium_gte?(version)\n  defined?(Selenium::WebDriver::VERSION) && (Gem::Version.new(Selenium::WebDriver::VERSION) >= Gem::Version.new(version))\nend\n\nCapybara.register_driver :selenium_chrome_remote do |app|\n  ensure_selenium_running!\n\n  url = \"http://#{selenium_host}:#{selenium_port}/wd/hub\"\n  browser_options = Selenium::WebDriver::Chrome::Options.new\n\n  Capybara::Selenium::Driver.new app,\n                                 browser: :remote,\n                                 options: browser_options,\n                                 url: url\nend\n\nCHROME_REMOTE_DRIVER = :selenium_chrome_remote\n\nmodule TestSessions\n  Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger download]\n\nCapybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when /Capybara::Session selenium_chrome_remote node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  when /Capybara::Session selenium_chrome_remote node #shadow_root/\n    skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)\n  end\nend\n\nRSpec.describe 'Capybara::Session with remote Chrome' do\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::Chrome, CHROME_REMOTE_DRIVER\n  end\n\n  it 'is considered to be chrome' do\n    expect(session.driver.browser.browser).to eq :chrome\n  end\n\n  describe 'log access' do\n    let(:logs) do\n      session.driver.browser.then do |chrome_driver|\n        chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage\n      end.logs\n    end\n\n    it 'does not error when getting log types' do\n      expect do\n        logs.available_types\n      end.not_to raise_error\n    end\n\n    it 'does not error when getting logs' do\n      expect do\n        logs.get(:browser)\n      end.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_edge.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\n# unless ENV['CI']\n#   Selenium::WebDriver::Edge::Service.driver_path = '/usr/local/bin/msedgedriver'\n# end\n\nSelenium::WebDriver.logger.ignore(:selenium_manager)\n\nif Selenium::WebDriver::Platform.mac?\n  Selenium::WebDriver::Edge.path = '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'\nend\n\nCapybara.register_driver :selenium_edge do |app|\n  # ::Selenium::WebDriver.logger.level = \"debug\"\n  # If we don't create an options object the path set above won't be used\n\n  # browser_options = Selenium::WebDriver::Edge::Options.new\n  # browser_options.add_argument('--headless') if ENV['HEADLESS']\n\n  browser_options = if ENV['HEADLESS']\n    Selenium::WebDriver::Options.edge(args: ['--headless=new'])\n  else\n    Selenium::WebDriver::Options.edge\n  end\n\n  Capybara::Selenium::Driver.new(app, browser: :edge, options: browser_options).tap do |driver|\n    driver.browser\n    driver.download_path = Capybara.save_path\n  end\nend\n\nmodule TestSessions\n  SeleniumEdge = Capybara::Session.new(:selenium_edge, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger]\n\nCapybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Edge) if ENV['CI']\n\nCapybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when 'Capybara::Session selenium #attach_file with a block can upload by clicking the file input'\n    pending \"Edge doesn't allow clicking on file inputs\"\n  when /Capybara::Session selenium node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  end\nend\n\nRSpec.describe 'Capybara::Session with Edge', capybara_skip: skipped_tests do\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::SeleniumEdge, :selenium_edge\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_firefox.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\nSelenium::WebDriver.logger.ignore(:selenium_manager)\n\nbrowser_options = Selenium::WebDriver::Firefox::Options.new\nbrowser_options.add_argument '-headless' if ENV['HEADLESS']\n# browser_options.add_option(\"log\", {\"level\": \"trace\"})\n\nbrowser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |profile|\n  profile['browser.download.dir'] = Capybara.save_path\n  profile['browser.download.folderList'] = 2\n  profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'\n  profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7\n  profile['accessibility.tabfocus'] = 7 # make tab move over links too\nend\n\nCapybara.register_driver :selenium_firefox do |app|\n  # ::Selenium::WebDriver.logger.level = \"debug\"\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  driver_options = { browser: :firefox, timeout: 31 }.tap do |opts|\n    opts[options_key] = browser_options\n    # Get a trace level log from geckodriver\n    # :driver_opts => { args: ['-vv'] }\n  end\n\n  Capybara::Selenium::Driver.new(app, **driver_options)\nend\n\nCapybara.register_driver :selenium_firefox_not_clear_storage do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  driver_options = { browser: :firefox, clear_local_storage: false, clear_session_storage: false }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **driver_options)\nend\n\nmodule TestSessions\n  SeleniumFirefox = Capybara::Session.new(:selenium_firefox, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger]\n\nCapybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Firefox) if ENV['CI']\n\nCapybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when 'Capybara::Session selenium node #click should allow multiple modifiers'\n    pending \"Firefox on OSX doesn't generate an event for shift+control+click\" if firefox_gte?(62, @session) && Selenium::WebDriver::Platform.mac?\n  when /^Capybara::Session selenium node #double_click/\n    pending \"selenium-webdriver/geckodriver doesn't generate double click event\" if firefox_lt?(59, @session)\n  when 'Capybara::Session selenium #accept_prompt should accept the prompt with a blank response when there is a default'\n    pending \"Geckodriver doesn't set a blank response in FF < 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1486485\" if firefox_lt?(63, @session)\n  when 'Capybara::Session selenium #attach_file with multipart form should fire change once when uploading multiple files from empty'\n    pending \"FF < 62 doesn't support setting all files at once\" if firefox_lt?(62, @session)\n  when 'Capybara::Session selenium #accept_confirm should work with nested modals'\n    skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)\n    skip 'Hangs in 69 <= FF < 71 - Dont know what issue for this - previous issue was closed as fixed but it is not' if firefox_gte?(69, @session) && firefox_lt?(71, @session)\n    skip 'Broken again intermittently in FF 71 - jus skip it' if firefox_lt?(109, @session) # don't really know when it was fixed\n  when 'Capybara::Session selenium #click_link can download a file'\n    skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?\n  when 'Capybara::Session selenium #reset_session! removes ALL cookies'\n    pending \"Geckodriver doesn't provide a way to remove cookies outside the current domain\"\n  when /drag_to.*HTML5/\n    pending \"Firefox < 62 doesn't support a DataTransfer constructor\" if firefox_lt?(62.0, @session)\n  when 'Capybara::Session selenium #accept_alert should handle the alert if the page changes',\n       'Capybara::Session selenium #accept_alert with an asynchronous alert should accept the alert'\n    skip 'No clue what Firefox is doing here - works fine on MacOS locally' if firefox_lt?(109, @session) # don't really know when it was fixed\n  when 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',\n       'Capybara::Session selenium node #shadow_root should find nested shadow roots',\n       'Capybara::Session selenium node #shadow_root should click on elements',\n       'Capybara::Session selenium node #shadow_root should use convenience methods once moved to a descendant of the shadow root',\n       'Capybara::Session selenium node #shadow_root should produce error messages when failing',\n       'Capybara::Session with firefox with selenium driver #evaluate_script returns a shadow root'\n    pending \"Firefox doesn't yet have full W3C shadow root support\" if firefox_lt?(113, @session)\n  when 'Capybara::Session selenium #fill_in should handle carriage returns with line feeds in a textarea correctly'\n    pending 'Not sure what firefox is doing here'\n  when /Capybara::Session selenium node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  when /Capybara::Session selenium node #shadow_root/\n    skip 'Not supported with this geckodriver version' if geckodriver_lt?('0.31.0', @session)\n  when /Capybara::Session selenium node #set should submit single text input forms if ended with \\\\n/\n    pending 'Firefox/geckodriver doesn\\'t submit with values ending in \\n'\n  when /Capybara::Session selenium #click_button should work with popovers/\n    skip \"Firefox doesn't currently support popover functionality\" if firefox_lt?(125, @session)\n  when /popover/\n    pending \"Firefox doesn't currently support popover functionality\" if firefox_lt?(125, @session)\n  end\nend\n\nRSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/MultipleDescribes\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::SeleniumFirefox, :selenium_firefox\n  end\n\n  describe 'filling in Firefox-specific date and time fields with keystrokes' do\n    let(:datetime) { Time.new(1983, 6, 19, 6, 30) }\n    let(:session) { TestSessions::SeleniumFirefox }\n\n    before do\n      session.visit('/form')\n    end\n\n    it 'should fill in a date input with a String' do\n      session.fill_in('form_date', with: datetime.to_date.iso8601)\n      session.click_button('awesome')\n      expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date\n    end\n\n    it 'should fill in a time input with a String' do\n      session.fill_in('form_time', with: datetime.to_time.strftime('%T'))\n      session.click_button('awesome')\n      results = extract_results(session)['time']\n      expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')\n    end\n\n    it 'should fill in a datetime input with a String' do\n      pending 'Need to figure out what string format this will actually accept'\n      session.fill_in('form_datetime', with: datetime.iso8601)\n      session.click_button('awesome')\n      expect(Time.parse(extract_results(session)['datetime'])).to eq datetime\n    end\n  end\nend\n\nRSpec.describe Capybara::Selenium::Driver do\n  let(:driver) { described_class.new(TestApp, browser: :firefox, options: browser_options) }\n\n  describe '#quit' do\n    it 'should reset browser when quit' do\n      expect(driver.browser).to be_truthy\n      driver.quit\n      # access instance variable directly so we don't create a new browser instance\n      expect(driver.instance_variable_get(:@browser)).to be_nil\n    end\n\n    context 'with errors' do\n      let!(:original_browser) { driver.browser }\n\n      after do\n        # Ensure browser is actually quit so we don't leave hanging processe\n        RSpec::Mocks.space.proxy_for(original_browser).reset\n        original_browser.quit\n      end\n\n      it 'warns UnknownError returned during quit because the browser is probably already gone' do\n        allow(driver).to receive(:warn)\n        allow(driver.browser).to(\n          receive(:quit)\n          .and_raise(Selenium::WebDriver::Error::UnknownError, 'random message')\n        )\n\n        expect { driver.quit }.not_to raise_error\n        expect(driver.instance_variable_get(:@browser)).to be_nil\n        expect(driver).to have_received(:warn).with(/random message/)\n      end\n\n      it 'ignores silenced UnknownError returned during quit because the browser is almost definitely already gone' do\n        allow(driver).to receive(:warn)\n        allow(driver.browser).to(\n          receive(:quit)\n          .and_raise(Selenium::WebDriver::Error::UnknownError, 'Error communicating with the remote browser')\n        )\n\n        expect { driver.quit }.not_to raise_error\n        expect(driver.instance_variable_get(:@browser)).to be_nil\n        expect(driver).not_to have_received(:warn)\n      end\n    end\n  end\n\n  context 'storage' do\n    describe '#reset!' do\n      it 'clears storage by default' do\n        session = TestSessions::SeleniumFirefox\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.driver.browser.execute_script('return localStorage.length')).to eq(0)\n        expect(session.driver.browser.execute_script('return sessionStorage.length')).to eq(0)\n      end\n\n      it 'does not clear storage when false' do\n        session = Capybara::Session.new(:selenium_firefox_not_clear_storage, TestApp)\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.driver.browser.execute_script('return localStorage.length')).to eq(1)\n        expect(session.driver.browser.execute_script('return sessionStorage.length')).to eq(1)\n      end\n    end\n  end\n\n  context 'timeout' do\n    it 'sets the http client read timeout' do\n      expect(TestSessions::SeleniumFirefox.driver.browser.send(:bridge).http.read_timeout).to eq 31\n    end\n  end\nend\n\nRSpec.describe Capybara::Selenium::Node do\n  describe '#click' do\n    it 'warns when attempting on a table row' do\n      session = TestSessions::SeleniumFirefox\n      session.visit('/tables')\n      tr = session.find(:css, '#agent_table tr:first-child')\n      allow(tr.base).to receive(:warn)\n      tr.click\n      expect(tr.base).to have_received(:warn).with(/Clicking the first cell in the row instead/)\n    end\n\n    it 'should allow multiple modifiers', requires: [:js] do\n      session = TestSessions::SeleniumFirefox\n      session.visit('with_js')\n      # Firefox v62+ doesn't generate an event for control+shift+click\n      session.find(:css, '#click-test').click(:alt, :ctrl, :meta)\n      # it also triggers a contextmenu event when control is held so don't check click type\n      expect(session).to have_link('Has been alt control meta')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_firefox_remote.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\ndef selenium_host\n  ENV.fetch('SELENIUM_HOST', '0.0.0.0')\nend\n\ndef selenium_port\n  ENV.fetch('SELENIUM_PORT', 4445)\nend\n\ndef ensure_selenium_running!\n  timer = Capybara::Helpers.timer(expire_in: 20)\n  begin\n    TCPSocket.open(selenium_host, selenium_port)\n  rescue StandardError\n    if timer.expired?\n      raise 'Selenium is not running. ' \\\n            \"You can run a selenium server easily with: \\n. \" \\\n            '$ docker-compose up -d selenium_firefox'\n    else\n      puts 'Waiting for Selenium docker instance...'\n      sleep 1\n      retry\n    end\n  end\nend\n\nCapybara.register_driver :selenium_firefox_remote do |app|\n  ensure_selenium_running!\n\n  url = \"http://#{selenium_host}:#{selenium_port}/wd/hub\"\n  browser_options = Selenium::WebDriver::Firefox::Options.new\n\n  Capybara::Selenium::Driver.new app,\n                                 browser: :remote,\n                                 options: browser_options,\n                                 url: url\nend\n\nFIREFOX_REMOTE_DRIVER = :selenium_firefox_remote\n\nmodule TestSessions\n  RemoteFirefox = Capybara::Session.new(FIREFOX_REMOTE_DRIVER, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger download]\n\nCapybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when 'Capybara::Session selenium_firefox_remote node #click should allow multiple modifiers'\n    skip \"Firefox doesn't generate an event for shift+control+click\" if firefox_gte?(62, @session)\n  when 'Capybara::Session selenium_firefox_remote #accept_prompt should accept the prompt with a blank response when there is a default'\n    pending \"Geckodriver doesn't set a blank response in FF < 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1486485\" if firefox_lt?(63, @session)\n  when 'Capybara::Session selenium_firefox_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'\n    pending \"FF < 62 doesn't support setting all files at once\" if firefox_lt?(62, @session)\n  when 'Capybara::Session selenium_firefox_remote #reset_session! removes ALL cookies'\n    pending \"Geckodriver doesn't provide a way to remove cookies outside the current domain\"\n  when /#accept_confirm should work with nested modals$/\n    # skip because this is timing based and hence flaky when set to pending\n    skip 'Broken in FF 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session)\n  when 'Capybara::Session selenium_firefox_remote #fill_in should handle carriage returns with line feeds in a textarea correctly'\n    pending 'Not sure what firefox is doing here'\n  when 'Capybara::Session selenium_firefox_remote node #shadow_root should find elements inside the shadow dom using CSS',\n       'Capybara::Session selenium_firefox_remote node #shadow_root should find nested shadow roots',\n       'Capybara::Session selenium_firefox_remote node #shadow_root should click on elements',\n       'Capybara::Session selenium_firefox_remote node #shadow_root should use convenience methods once moved to a descendant of the shadow root',\n       'Capybara::Session selenium_firefox_remote node #shadow_root should produce error messages when failing',\n       'Capybara::Session with remote firefox with selenium driver #evaluate_script returns a shadow root'\n    pending \"Firefox doesn't yet have full W3C shadow root support\"\n  when /Capybara::Session selenium_firefox_remote node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  when /Capybara::Session selenium_firefox_remote node #shadow_root/\n    skip 'Not supported with this geckodriver version' if geckodriver_lt?('0.31.0', @session)\n  when /Capybara::Session selenium node #set should submit single text input forms if ended with \\\\n/\n    pending 'Firefox/geckodriver doesn\\'t submit with values ending in \\n'\n  when /Capybara::Session selenium_firefox_remote #click_button should work with popovers/\n    skip \"Firefox doesn't currently support popover functionality\"\n  when /popover/\n    pending \"Firefox doesn't currently support popover functionality\"\n  end\nend\n\nRSpec.describe 'Capybara::Session with remote firefox' do\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER\n  end\n\n  it 'is considered to be firefox' do\n    expect(session.driver.browser.browser).to eq :firefox\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_ie.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\n# if ENV['CI']\n#   if ::Selenium::WebDriver::Service.respond_to? :driver_path=\n#     ::Selenium::WebDriver::IE::Service\n#   else\n#     ::Selenium::WebDriver::IE\n#   end.driver_path = 'C:\\Tools\\WebDriver\\IEDriverServer.exe'\n# end\n\ndef selenium_host\n  ENV.fetch('SELENIUM_HOST', '192.168.56.102')\nend\n\ndef selenium_port\n  ENV.fetch('SELENIUM_PORT', 4444)\nend\n\ndef server_host\n  ENV.fetch('SERVER_HOST', '10.24.4.135')\nend\n\nCapybara.register_driver :selenium_ie do |app|\n  # ::Selenium::WebDriver.logger.level = \"debug\"\n  options = Selenium::WebDriver::IE::Options.new\n  # options.require_window_focus = true\n  # options.add_option(\"log\", {\"level\": \"trace\"})\n\n  if ENV['REMOTE']\n    Capybara.server_host = server_host\n\n    url = \"http://#{selenium_host}:#{selenium_port}/wd/hub\"\n    Capybara::Selenium::Driver.new(app,\n                                   browser: :remote,\n                                   options: options,\n                                   url: url)\n  else\n    Capybara::Selenium::Driver.new(\n      app,\n      browser: :ie,\n      options: options\n    )\n  end\nend\n\nmodule TestSessions\n  SeleniumIE = Capybara::Session.new(:selenium_ie, TestApp)\nend\n\nTestSessions::SeleniumIE.current_window.resize_to(800, 500)\n\nskipped_tests = %i[response_headers status_code trigger modals hover form_attribute windows]\n\nCapybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::IE) if ENV['CI']\n\nTestSessions::SeleniumIE.current_window.resize_to(1600, 1200)\n\nCapybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when /#refresh it reposts$/\n    skip 'IE insists on prompting without providing a way to suppress'\n  when /#click_link can download a file$/\n    skip 'Not sure how to configure IE for automatic downloading'\n  when /#fill_in with Date /\n    pending \"IE 11 doesn't support date input types\"\n  when /#click_link_or_button with :disabled option happily clicks on links which incorrectly have the disabled attribute$/\n    skip 'IE 11 obeys non-standard disabled attribute on anchor tag'\n  when /#click should allow modifiers$/, /#double_click should allow modifiers$/\n    pending \"Doesn't work with IE for some unknown reason$\"\n    pending \"Doesn't work with IE for some unknown reason$\"\n  when /#click should allow multiple modifiers$/, /#right_click should allow modifiers$/\n    skip \"Windows can't :meta click because :meta triggers start menu\"\n  when /#double_click should allow multiple modifiers$/\n    skip \"Windows can't :alt double click due to being properties shortcut\"\n  when /#has_css\\? should support case insensitive :class and :id options$/\n    pending \"IE doesn't support case insensitive CSS selectors\"\n  when /#reset_session! removes ALL cookies$/\n    pending \"IE driver doesn't provide a way to remove ALL cookies\"\n  when /#click_button should send button in document order$/\n    pending \"IE 11 doesn't support the 'form' attribute\"\n  when /#click_button should follow permanent redirects that maintain method$/\n    pending \"Window 7 and 8.1 don't support 308 http status code\"\n  when /#scroll_to can scroll an element to the center of the viewport$/,\n       /#scroll_to can scroll an element to the center of the scrolling element$/\n    pending \"IE doesn't support ScrollToOptions\"\n  when /#attach_file with multipart form should fire change once for each set of files uploaded$/,\n       /#attach_file with multipart form should fire change once when uploading multiple files from empty$/,\n       /#attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files$/\n    pending \"IE requires all files be uploaded from same directory. Selenium doesn't provide that.\" if ENV['REMOTE']\n  when %r{#attach_file with multipart form should send content type image/jpeg when uploading an image$}\n    pending 'IE gets text/plain type for some reason'\n  # when /#click should not retry clicking when wait is disabled$/\n  #   Fixed in IEDriverServer 3.141.0.5\n  #   pending \"IE driver doesn't error when clicking on covered elements, it just clicks the wrong element\"\n  when /#click should go to the same page if href is blank$/\n    pending 'IE treats blank href as a parent request (against HTML spec)'\n  when /#attach_file with a block/\n    skip 'Hangs IE testing for unknown reason'\n  when /drag_to.*HTML5/\n    pending \"IE doesn't support a DataTransfer constructor\"\n  when /template elements should not be visible/\n    skip \"IE doesn't support template elements\"\n  when /Element#drop/\n    pending \"IE doesn't support DataTransfer constructor\"\n  when /Capybara::Session selenium_chrome node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  end\nend\n\nRSpec.describe 'Capybara::Session with Internet Explorer', capybara_skip: skipped_tests do # rubocop:disable RSpec/MultipleDescribes\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::SeleniumIE, :selenium_ie\n  end\nend\n\nRSpec.describe Capybara::Selenium::Node do\n  it '#right_click should allow modifiers' do\n    # pending \"Actions API doesn't appear to work for this\"\n    session = TestSessions::SeleniumIE\n    session.visit('/with_js')\n    el = session.find(:css, '#click-test')\n    el.right_click(:control)\n    expect(session).to have_link('Has been control right clicked')\n  end\n\n  it '#click should allow multiple modifiers' do\n    # pending \"Actions API doesn't appear to work for this\"\n    session = TestSessions::SeleniumIE\n    session.visit('with_js')\n    # IE triggers system behavior with :meta so can't use those here\n    session.find(:css, '#click-test').click(:ctrl, :shift, :alt)\n    expect(session).to have_link('Has been alt control shift clicked')\n  end\n\n  it '#double_click should allow modifiers' do\n    # pending \"Actions API doesn't appear to work for this\"\n    session = TestSessions::SeleniumIE\n    session.visit('/with_js')\n    session.find(:css, '#click-test').double_click(:shift)\n    expect(session).to have_link('Has been shift double clicked')\n  end\nend\n"
  },
  {
    "path": "spec/selenium_spec_safari.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\nrequire 'shared_selenium_session'\nrequire 'shared_selenium_node'\nrequire 'rspec/shared_spec_matchers'\n\nSAFARI_DRIVER = :selenium_safari\n\n# if ::Selenium::WebDriver::Service.respond_to? :driver_path=\n#   ::Selenium::WebDriver::Safari::Service\n# else\n#   ::Selenium::WebDriver::Safari\n# end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'\n\nbrowser_options = Selenium::WebDriver::Safari::Options.new\n# browser_options.headless! if ENV['HEADLESS']\n\nCapybara.register_driver :selenium_safari do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  driver_options = { browser: :safari, timeout: 30 }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|\n    # driver.browser.download_path = Capybara.save_path\n  end\nend\n\nCapybara.register_driver :selenium_safari_not_clear_storage do |app|\n  version = Capybara::Selenium::Driver.load_selenium\n  options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options\n  driver_options = {\n    browser: :safari,\n    clear_local_storage: false,\n    clear_session_storage: false,\n    timeout: 30\n  }.tap do |opts|\n    opts[options_key] = browser_options\n  end\n\n  Capybara::Selenium::Driver.new(app, **driver_options)\nend\n\nmodule TestSessions\n  Safari = Capybara::Session.new(SAFARI_DRIVER, TestApp)\nend\n\nskipped_tests = %i[response_headers status_code trigger windows drag]\n\nCapybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Safari) if ENV['CI']\n\nCapybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybara_skip: skipped_tests do |example|\n  case example.metadata[:full_description]\n  when /click_link can download a file/\n    skip \"safaridriver doesn't provide a way to set the download directory\"\n  when /Capybara::Session selenium_safari Capybara::Window#maximize/\n    pending \"Safari headless doesn't support maximize\" if ENV['HEADLESS']\n  when /Capybara::Session selenium_safari #visit without a server/,\n       /Capybara::Session selenium_safari #visit with Capybara.app_host set should override server/,\n       /Capybara::Session selenium_safari #reset_session! When reuse_server == false raises any standard errors caught inside the server during a second session/\n    skip \"Safari webdriver doesn't support multiple sessions\"\n  when /Capybara::Session selenium_safari #click_link with alternative text given to a contained image/,\n       'Capybara::Session selenium_safari #click_link_or_button with enable_aria_label should click on link'\n    pending 'safaridriver thinks these links are non-interactable for some unknown reason'\n  when /Capybara::Session selenium_safari #attach_file with a block can upload by clicking the file input/\n    skip \"safaridriver doesn't allow clicking on file inputs\"\n  when /Capybara::Session selenium_safari #within_frame works if the frame is closed/,\n       /Capybara::Session selenium_safari #switch_to_frame works if the frame is closed/\n    skip 'Safari has a race condition when clicking an element that causes the frame to close. It will sometimes raise a NoSuchFrameError'\n  when /Capybara::Session selenium_safari #reset_session! removes ALL cookies/\n    skip 'Safari webdriver can only remove cookies for the current domain'\n  when /Capybara::Session selenium_safari #refresh it reposts/\n    skip \"Safari opens an alert that can't be closed\"\n  when 'Capybara::Session selenium_safari node #double_click should allow to adjust the offset',\n       'Capybara::Session selenium_safari node #double_click should double click an element'\n    pending \"safardriver doesn't generate a double click event\"\n  when 'Capybara::Session selenium_safari node #double_click should allow modifiers'\n    pending \"safaridriver doesn't generate double click with key modifiers\"\n  when /when w3c_click_offset is true should offset/\n    pending 'w3c_click_offset is not currently supported with safaridriver'\n  when 'Capybara::Session selenium_safari #go_back should fetch a response from the driver from the previous page',\n       'Capybara::Session selenium_safari #go_forward should fetch a response from the driver from the previous page'\n    skip 'safaridriver loses the ability to find elements in the document after `go_back`'\n  when 'Capybara::Session selenium node #shadow_root should get the shadow root',\n    'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',\n    'Capybara::Session selenium node #shadow_root should find nested shadow roots'\n    pending \"Safari doesn't yet have W3C shadow root support\"\n  when /Capybara::Session selenium_chrome node #shadow_root should get visible text/\n    pending \"Selenium doesn't currently support getting visible text for shadow root elements\"\n  end\nend\n\nRSpec.describe 'Capybara::Session with safari' do\n  include Capybara::SpecHelper\n\n  ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|\n    include_examples examples, TestSessions::Safari, SAFARI_DRIVER\n  end\n\n  context 'storage' do\n    describe '#reset!' do\n      it 'clears storage by default' do\n        session = TestSessions::Safari\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty\n      end\n\n      it 'does not clear storage when false' do\n        skip \"Safari webdriver doesn't support multiple sessions\"\n        session = Capybara::Session.new(:selenium_safari_not_clear_storage, TestApp)\n        session.visit('/with_js')\n        session.find(:css, '#set-storage').click\n        session.reset!\n        session.visit('/with_js')\n        expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty\n        expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty\n      end\n    end\n  end\n\n  context 'timeout' do\n    it 'sets the http client read timeout' do\n      expect(TestSessions::Safari.driver.browser.send(:bridge).http.read_timeout).to eq 30\n    end\n  end\n\n  describe 'filling in Safari-specific date and time fields with keystrokes' do\n    let(:datetime) { Time.new(1983, 6, 19, 6, 30) }\n    let(:session) { TestSessions::Safari }\n\n    before do\n      session.visit('/form')\n    end\n\n    it 'should fill in a date input with a String' do\n      session.fill_in('form_date', with: '06/19/1983')\n      session.click_button('awesome')\n      expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date\n    end\n\n    it 'should fill in a time input with a String' do\n      # Safari doesn't support time inputs - so this is just a text input\n      session.fill_in('form_time', with: '06:30A')\n      session.click_button('awesome')\n      results = extract_results(session)['time']\n      expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')\n    end\n\n    it 'should fill in a datetime input with a String' do\n      pending \"Safari doesn't support datetime inputs\"\n      session.fill_in('form_datetime', with: \"06/19/1983\\t06:30A\")\n      session.click_button('awesome')\n      expect(Time.parse(extract_results(session)['datetime'])).to eq datetime\n    end\n  end\nend\n"
  },
  {
    "path": "spec/server_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Server do\n  it 'should spool up a rack server' do\n    app = proc { |_env| [200, {}, ['Hello Server!']] }\n    server = described_class.new(app).boot\n\n    res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }\n\n    expect(res.body).to include('Hello Server')\n  end\n\n  it 'should do nothing when no server given' do\n    expect do\n      described_class.new(nil).boot\n    end.not_to raise_error\n  end\n\n  it 'should bind to the specified host' do\n    # TODO: travis with jruby in container mode has an issue with this test\n    skip 'This platform has an issue with this test' if (ENV.fetch('TRAVIS', nil) && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?\n\n    begin\n      app = proc { |_env| [200, {}, ['Hello Server!']] }\n\n      Capybara.server_host = '127.0.0.1'\n      server = described_class.new(app).boot\n      res = Net::HTTP.get(URI(\"http://127.0.0.1:#{server.port}\"))\n      expect(res).to eq('Hello Server!')\n\n      Capybara.server_host = '0.0.0.0'\n      server = described_class.new(app).boot\n      res = Net::HTTP.get(URI(\"http://127.0.0.1:#{server.port}\"))\n      expect(res).to eq('Hello Server!')\n    ensure\n      Capybara.server_host = nil\n    end\n  end\n\n  it 'should use specified port' do\n    Capybara.server_port = 22789\n\n    app = proc { |_env| [200, {}, ['Hello Server!']] }\n    server = described_class.new(app).boot\n\n    res = Net::HTTP.start(server.host, 22789) { |http| http.get('/') }\n    expect(res.body).to include('Hello Server')\n\n    Capybara.server_port = nil\n  end\n\n  it 'should use given port' do\n    app = proc { |_env| [200, {}, ['Hello Server!']] }\n    server = described_class.new(app, port: 22790).boot\n\n    res = Net::HTTP.start(server.host, 22790) { |http| http.get('/') }\n    expect(res.body).to include('Hello Server')\n\n    Capybara.server_port = nil\n  end\n\n  it 'should find an available port' do\n    responses = ['Hello Server!', 'Hello Second Server!']\n    apps = responses.map do |response|\n      proc { |_env| [200, {}, [response]] }\n    end\n    servers = apps.map { |app| described_class.new(app).boot }\n\n    servers.each_with_index do |server, idx|\n      result = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }\n      expect(result.body).to include(responses[idx])\n    end\n  end\n\n  it 'should handle that getting available ports fails randomly' do\n    # Use a port to force a EADDRINUSE error to be generated\n    server = TCPServer.new('0.0.0.0', 0)\n    server_port = server.addr[1]\n    d_server = instance_double(TCPServer, addr: [nil, server_port, nil, nil], close: nil)\n    call_count = 0\n    allow(TCPServer).to receive(:new).and_wrap_original do |m, *args|\n      call_count.zero? ? d_server : m.call(*args)\n    ensure\n      call_count += 1\n    end\n\n    port = described_class.new(Object.new, host: '0.0.0.0').port\n    expect(port).not_to eq(server_port)\n  ensure\n    server&.close\n  end\n\n  it 'should return its #base_url' do\n    app = proc { |_env| [200, {}, ['Hello Server!']] }\n    server = described_class.new(app).boot\n    uri = Addressable::URI.parse(server.base_url)\n    expect(uri.to_hash).to include(scheme: 'http', host: server.host, port: server.port)\n  end\n\n  it 'should call #clamp on the puma configuration to ensure that environment is a string' do\n    Capybara.server = :puma\n    app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }\n    require 'puma'\n    allow(Puma::Server).to receive(:new).and_wrap_original do |method, app, events, options|\n      # If #clamp is not called on the puma config then this will be a Proc\n      expect(options.fetch(:environment)).to be_a(String)\n      method.call(app, events, options)\n    end\n    server = described_class.new(app_proc).boot\n    expect(Puma::Server).to have_received(:new).with(\n      anything,\n      anything,\n      satisfy { |opts| opts.final_options[:Port] == server.port }\n    )\n  ensure\n    Capybara.server = :default\n  end\n\n  it 'should not emit any warnings when booting puma' do\n    Capybara.server = :puma\n    app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }\n    require 'puma'\n\n    expect do\n      described_class.new(app_proc).boot\n    end.not_to output.to_stderr\n  ensure\n    Capybara.server = :default\n  end\n\n  it 'should support SSL' do\n    key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')\n    cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')\n    Capybara.server = :puma, { Host: \"ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}\" }\n    app = proc { |_env| [200, {}, ['Hello SSL Server!']] }\n    server = described_class.new(app).boot\n\n    expect do\n      Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }\n    end.to(raise_error do |e|\n      expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true\n    end)\n\n    res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|\n      https.get('/')\n    end\n\n    expect(res.body).to include('Hello SSL Server!')\n    uri = Addressable::URI.parse(server.base_url)\n    expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)\n  ensure\n    Capybara.server = :default\n  end\n\n  context 'When Capybara.reuse_server is true' do\n    let!(:old_reuse_server) { Capybara.reuse_server }\n\n    before do\n      Capybara.reuse_server = true\n    end\n\n    after do\n      Capybara.reuse_server = old_reuse_server\n    end\n\n    it 'should use the existing server if it already running' do\n      app = proc { |_env| [200, {}, ['Hello Server!']] }\n\n      servers = Array.new(2) { described_class.new(app).boot }\n\n      servers.each do |server|\n        res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }\n        expect(res.body).to include('Hello Server')\n      end\n\n      expect(servers[0].port).to eq(servers[1].port)\n    end\n\n    it 'detects and waits for all reused server sessions pending requests' do\n      done = 0\n\n      app = proc do |env|\n        request = Rack::Request.new(env)\n        sleep request.params['wait_time'].to_f\n        done += 1\n        [200, {}, ['Hello Server!']]\n      end\n\n      server1 = described_class.new(app).boot\n      server2 = described_class.new(app).boot\n\n      expect do\n        start_request(server1, 1.0)\n        start_request(server2, 3.0)\n        server1.wait_for_pending_requests\n      end.to change { done }.from(0).to(2)\n      expect(server2.send(:pending_requests?)).to be(false)\n    end\n  end\n\n  context 'When Capybara.reuse_server is false' do\n    before do\n      @old_reuse_server = Capybara.reuse_server\n      Capybara.reuse_server = false\n    end\n\n    after do\n      Capybara.reuse_server = @old_reuse_server # rubocop:disable RSpec/InstanceVariable\n    end\n\n    it 'should not reuse an already running server' do\n      app = proc { |_env| [200, {}, ['Hello Server!']] }\n\n      servers = Array.new(2) { described_class.new(app).boot }\n\n      servers.each do |server|\n        res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }\n        expect(res.body).to include('Hello Server')\n      end\n\n      expect(servers[0].port).not_to eq(servers[1].port)\n    end\n\n    it 'detects and waits for only one sessions pending requests' do\n      done = 0\n\n      app = proc do |env|\n        request = Rack::Request.new(env)\n        sleep request.params['wait_time'].to_f\n        done += 1\n        [200, {}, ['Hello Server!']]\n      end\n\n      server1 = described_class.new(app).boot\n      server2 = described_class.new(app).boot\n\n      expect do\n        start_request(server1, 1.0)\n        start_request(server2, 3.0)\n        server1.wait_for_pending_requests\n      end.to change { done }.from(0).to(1)\n      expect(server2.send(:pending_requests?)).to be(true)\n      expect do\n        server2.wait_for_pending_requests\n      end.to change { done }.from(1).to(2)\n    end\n  end\n\n  it 'should raise server errors when the server errors before the timeout' do\n    Capybara.register_server :kaboom do\n      sleep 0.1\n      raise 'kaboom'\n    end\n    Capybara.server = :kaboom\n\n    expect do\n      described_class.new(proc { |e| }).boot\n    end.to raise_error(RuntimeError, 'kaboom')\n  ensure\n    Capybara.server = :default\n  end\n\n  it 'should raise an error when there are pending requests' do\n    app = proc do |env|\n      request = Rack::Request.new(env)\n      sleep request.params['wait_time'].to_f\n      [200, {}, ['Hello Server!']]\n    end\n\n    server = described_class.new(app).boot\n\n    expect do\n      start_request(server, 59.0)\n      server.wait_for_pending_requests\n    end.not_to raise_error\n\n    expect do\n      start_request(server, 61.0)\n      server.wait_for_pending_requests\n    end.to raise_error('Requests did not finish in 60 seconds: [\"/?wait_time=61.0\"]')\n  end\n\n  it 'is not #responsive? when Net::HTTP raises a SystemCallError' do\n    app = -> { [200, {}, ['Hello, world']] }\n    server = described_class.new(app)\n    allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)\n    expect(server.responsive?).to be false\n  end\n\n  [EOFError, Net::ReadTimeout].each do |err|\n    it \"should attempt an HTTPS connection if HTTP connection returns #{err}\" do\n      app = -> { [200, {}, ['Hello, world']] }\n      ordered_errors = [Errno::ECONNREFUSED, err]\n      allow(Net::HTTP).to receive(:start).with(anything, anything, hash_excluding(:use_ssl)) do\n        raise ordered_errors.shift\n      end\n      response = Net::HTTPSuccess.allocate\n      allow(response).to receive(:body).and_return app.object_id.to_s\n      allow(Net::HTTP).to receive(:start).with(anything, anything, hash_including(use_ssl: true)).and_return(response).once\n      described_class.new(app).boot\n      expect(Net::HTTP).to have_received(:start).exactly(3).times\n    end\n  end\n\n  def start_request(server, wait_time)\n    # Start request, but don't wait for it to finish\n    socket = TCPSocket.new(server.host, server.port)\n    socket.write \"GET /?wait_time=#{wait_time} HTTP/1.0\\r\\n\\r\\n\"\n    sleep 0.1\n    socket.close\n    sleep 0.1\n  end\nend\n"
  },
  {
    "path": "spec/session_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nRSpec.describe Capybara::Session do\n  describe '#new' do\n    it 'should raise an error if passed non-existent driver' do\n      expect do\n        described_class.new(:quox, TestApp).driver\n      end.to raise_error(Capybara::DriverNotFoundError)\n    end\n\n    it 'verifies a passed app is a rack app' do\n      expect do\n        described_class.new(:unknown, random: 'hash')\n      end.to raise_error TypeError, 'The second parameter to Session::new should be a rack app if passed.'\n    end\n  end\n\n  context 'current_driver' do\n    around do |example|\n      orig_driver = Capybara.current_driver\n      example.run\n      Capybara.current_driver = orig_driver\n    end\n\n    it 'is global when threadsafe false' do\n      Capybara.threadsafe = false\n      Capybara.current_driver = :selenium\n      thread = Thread.new do\n        Capybara.current_driver = :random\n      end\n      thread.join\n      expect(Capybara.current_driver).to eq :random\n    end\n\n    it 'is thread specific threadsafe true' do\n      Capybara.threadsafe = true\n      Capybara.current_driver = :selenium\n      thread = Thread.new do\n        Capybara.current_driver = :random\n      end\n      thread.join\n      expect(Capybara.current_driver).to eq :selenium\n    end\n  end\n\n  context 'session_name' do\n    around do |example|\n      orig_name = Capybara.session_name\n      example.run\n      Capybara.session_name = orig_name\n    end\n\n    it 'is global when threadsafe false' do\n      Capybara.threadsafe = false\n      Capybara.session_name = 'sess1'\n      thread = Thread.new do\n        Capybara.session_name = 'sess2'\n      end\n      thread.join\n      expect(Capybara.session_name).to eq 'sess2'\n    end\n\n    it 'is thread specific when threadsafe true' do\n      Capybara.threadsafe = true\n      Capybara.session_name = 'sess1'\n      thread = Thread.new do\n        Capybara.session_name = 'sess2'\n      end\n      thread.join\n      expect(Capybara.session_name).to eq 'sess1'\n    end\n  end\n\n  context 'quit' do\n    it 'will reset the driver' do\n      session = described_class.new(:rack_test, TestApp)\n      driver = session.driver\n      session.quit\n      expect(session.driver).not_to eql driver\n    end\n\n    it 'resets the document' do\n      session = described_class.new(:rack_test, TestApp)\n      document = session.document\n      session.quit\n      expect(session.document.base).not_to eql document.base\n    end\n  end\nend\n"
  },
  {
    "path": "spec/shared_selenium_node.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\n\nRSpec.shared_examples 'Capybara::Node' do |session, _mode|\n  let(:session) { session }\n\n  describe '#content_editable?' do\n    it 'returns true when the element is content editable' do\n      session.visit('/with_js')\n      expect(session.find(:css, '#existing_content_editable').base.content_editable?).to be true\n      expect(session.find(:css, '#existing_content_editable_child').base.content_editable?).to be true\n    end\n\n    it 'returns false when the element is not content editable' do\n      session.visit('/with_js')\n      expect(session.find(:css, '#drag').base.content_editable?).to be false\n    end\n  end\n\n  describe '#send_keys' do\n    it 'should process space' do\n      session.visit('/form')\n      session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])\n      expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'\n    end\n  end\n\n  describe '#[]' do\n    it 'should work for spellcheck' do\n      session.visit('/with_html')\n      expect(session.find('//input[@spellcheck=\"TRUE\"]')[:spellcheck]).to eq('true')\n      expect(session.find('//input[@spellcheck=\"FALSE\"]')[:spellcheck]).to eq('false')\n    end\n  end\n\n  describe '#set' do\n    it 'respects maxlength when using rapid set' do\n      session.visit('/form')\n      inp = session.find(:css, '#long_length')\n      value = (0...50).map { |i| ((i % 26) + 65).chr }.join\n      inp.set(value, rapid: true)\n      expect(inp.value).to eq value[0...35]\n    end\n  end\n\n  describe '#visible?' do\n    let(:bridge) do\n      session.driver.browser.send(:bridge)\n    end\n\n    around do |example|\n      native_displayed = session.driver.options[:native_displayed]\n      example.run\n      session.driver.options[:native_displayed] = native_displayed\n    end\n\n    before do\n      allow(bridge).to receive(:execute_atom).and_call_original\n    end\n\n    it 'will use native displayed if told to' do\n      session.driver.options[:native_displayed] = true\n      session.visit('/form')\n      session.find(:css, '#address1_city', visible: true)\n\n      expect(bridge).not_to have_received(:execute_atom)\n    end\n\n    it \"won't use native displayed if told not to\" do\n      session.driver.options[:native_displayed] = false\n      session.visit('/form')\n      session.find(:css, '#address1_city', visible: true)\n\n      expect(bridge).to have_received(:execute_atom).with(:isDisplayed, any_args)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/shared_selenium_session.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'selenium-webdriver'\n\nRSpec.shared_examples 'Capybara::Session' do |session, mode|\n  let(:session) { session }\n\n  context 'with selenium driver' do\n    describe '#driver' do\n      it 'should be a selenium driver' do\n        expect(session.driver).to be_an_instance_of(Capybara::Selenium::Driver)\n      end\n    end\n\n    describe '#mode' do\n      it 'should remember the mode' do\n        expect(session.mode).to eq(mode)\n      end\n    end\n\n    describe '#reset!' do\n      it 'freshly reset session should not be touched' do\n        session.instance_variable_set(:@touched, true)\n        session.reset!\n        expect(session.instance_variable_get(:@touched)).to be false\n      end\n    end\n\n    describe 'exit codes' do\n      let(:env) { { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s } }\n      let!(:orig_dir) { Dir.getwd }\n\n      before do\n        Dir.chdir(File.join(File.dirname(__FILE__), '..'))\n      end\n\n      after do\n        Dir.chdir(orig_dir)\n      end\n\n      it 'should have return code 1 when running selenium_driver_rspec_failure.rb' do\n        skip 'only setup for local non-headless' if headless_or_remote?\n        skip 'Not setup for edge' if edge?(session)\n\n        system(env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)\n        expect($CHILD_STATUS.exitstatus).to eq(1)\n      end\n\n      it 'should have return code 0 when running selenium_driver_rspec_success.rb' do\n        skip 'only setup for local non-headless' if headless_or_remote?\n        skip 'Not setup for edge' if edge?(session)\n\n        system(env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)\n        expect($CHILD_STATUS.exitstatus).to eq(0)\n      end\n    end\n\n    describe '#accept_alert', requires: [:modals] do\n      it 'supports a blockless mode' do\n        session.visit('/with_js')\n        session.click_link('Open alert')\n        session.accept_alert\n        expect { session.driver.browser.switch_to.alert }.to raise_error(session.driver.send(:modal_error))\n      end\n\n      it 'can be called before visiting' do\n        session.accept_alert 'Initial alert' do\n          session.visit('/initial_alert')\n        end\n        expect(session).to have_text('Initial alert page')\n      end\n    end\n\n    describe '#fill_in_with empty string and no options' do\n      it 'should trigger change when clearing a field' do\n        session.visit('/with_js')\n        session.fill_in('with_change_event', with: '')\n        # click outside the field to trigger the change event\n        session.find(:css, 'body').click\n        expect(session).to have_selector(:css, '.change_event_triggered', match: :one)\n      end\n    end\n\n    describe '#fill_in with { :clear => :backspace } fill_option', requires: [:js] do\n      before do\n        # Firefox has an issue with change events if the main window doesn't think it's focused\n        session.execute_script('window.focus()')\n      end\n\n      it 'should fill in a field, replacing an existing value' do\n        session.visit('/form')\n        session.fill_in('form_first_name',\n                        with: 'Harry',\n                        fill_options: { clear: :backspace })\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('Harry')\n      end\n\n      it 'should fill in a field, replacing an existing value, even with caret position' do\n        session.visit('/form')\n        session.find(:css, '#form_first_name').execute_script <<-JS\n          this.focus();\n          this.setSelectionRange(0, 0);\n        JS\n\n        session.fill_in('form_first_name',\n                        with: 'Harry',\n                        fill_options: { clear: :backspace })\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('Harry')\n      end\n\n      it 'should fill in if the option is set via global option' do\n        Capybara.default_set_options = { clear: :backspace }\n        session.visit('/form')\n        session.fill_in('form_first_name', with: 'Thomas')\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('Thomas')\n      end\n\n      it 'should only trigger onchange once' do\n        session.visit('/with_js')\n        sleep 2 if safari?(session) # Safari needs a delay (to load event handlers maybe ???)\n        session.fill_in('with_change_event',\n                        with: 'some value',\n                        fill_options: { clear: :backspace })\n        # click outside the field to trigger the change event\n        session.find(:css, '#with_focus_event').click\n        expect(session.find(:css, '.change_event_triggered', match: :one, wait: 5)).to have_text 'some value'\n      end\n\n      it 'should trigger change when clearing field' do\n        session.visit('/with_js')\n        session.fill_in('with_change_event',\n                        with: '',\n                        fill_options: { clear: :backspace })\n        # click outside the field to trigger the change event\n        session.find(:css, '#with_focus_event').click\n        expect(session).to have_selector(:css, '.change_event_triggered', match: :one, wait: 5)\n      end\n\n      it 'should trigger input event field_value.length times' do\n        session.visit('/with_js')\n        session.fill_in('with_change_event',\n                        with: '',\n                        fill_options: { clear: :backspace })\n        # click outside the field to trigger the change event\n        # session.find(:css, 'body').click\n        session.find(:css, 'h1', text: 'FooBar').click\n        expect(session).to have_xpath('//p[@class=\"input_event_triggered\"]', count: 13)\n      end\n    end\n\n    describe '#fill_in with { clear: :none } fill_options' do\n      it 'should append to content in a field' do\n        pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)\n\n        session.visit('/form')\n        session.fill_in('form_first_name',\n                        with: 'Harry',\n                        fill_options: { clear: :none })\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')\n      end\n\n      it 'works with rapid fill' do\n        pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)\n\n        long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join\n        session.visit('/form')\n        session.fill_in('form_first_name', with: long_string, fill_options: { clear: :none })\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq(\"John#{long_string}\")\n      end\n    end\n\n    describe '#fill_in with Date' do\n      before do\n        session.visit('/form')\n        session.find(:css, '#form_date').execute_script <<-JS\n          window.capybara_formDateFiredEvents = [];\n          var fd = this;\n          ['focus', 'input', 'change'].forEach(function(eventType) {\n            fd.addEventListener(eventType, function() { window.capybara_formDateFiredEvents.push(eventType); });\n          });\n        JS\n        # work around weird FF issue where it would create an extra focus issue in some cases\n        session.find(:css, 'h1', text: 'Form').click\n        # session.find(:css, 'body').click\n      end\n\n      it 'should generate standard events on changing value' do\n        pending \"IE 11 doesn't support date input type\" if ie?(session)\n        session.fill_in('form_date', with: Date.today)\n        expect(session.evaluate_script('window.capybara_formDateFiredEvents')).to eq %w[focus input change]\n      end\n\n      it 'should not generate input and change events if the value is not changed' do\n        pending \"IE 11 doesn't support date input type\" if ie?(session)\n        session.fill_in('form_date', with: Date.today)\n        session.fill_in('form_date', with: Date.today)\n        # Chrome adds an extra focus for some reason - ok for now\n        expect(session.evaluate_script('window.capybara_formDateFiredEvents')).to eq(%w[focus input change])\n      end\n    end\n\n    describe '#fill_in with { clear: Array } fill_options' do\n      it 'should pass the array through to the element' do\n        # this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful\n        session.visit('/form')\n        session.fill_in('form_first_name',\n                        with: 'Harry',\n                        fill_options: { clear: [[:shift, 'abc'], :backspace] })\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnABHarry')\n      end\n    end\n\n    describe '#fill_in with Emoji' do\n      it 'sends emojis' do\n        session.visit('/form')\n        session.fill_in('form_first_name', with: 'a😀cd😴 🛌🏽🇵🇹 e🤾🏽‍♀️f')\n        expect(session.find(:fillable_field, 'form_first_name').value).to eq('a😀cd😴 🛌🏽🇵🇹 e🤾🏽‍♀️f')\n      end\n    end\n\n    describe '#send_keys' do\n      it 'defaults to sending keys to the active_element' do\n        session.visit('/form')\n\n        expect(session.active_element).to match_selector(:css, 'body')\n\n        session.send_keys(:tab)\n\n        expect(session.active_element).to match_selector(:css, '[tabindex=\"1\"]')\n      end\n    end\n\n    describe '#path' do\n      it 'returns xpath' do\n        # this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver\n        session.visit('/path')\n        element = session.find(:link, 'Second Link')\n        expect(element.path).to eq('/HTML/BODY[1]/DIV[2]/A[1]')\n      end\n\n      it 'handles namespaces in xhtml' do\n        pending \"IE 11 doesn't handle all XPath querys (namespace-uri, etc)\" if ie?(session)\n        session.visit '/with_namespace'\n        rect = session.find(:css, 'div svg rect:first-of-type')\n        expect(rect.path).to eq(\"/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]\")\n        expect(session.find(:xpath, rect.path)).to eq rect\n      end\n\n      it 'handles default namespaces in html5' do\n        pending \"IE 11 doesn't handle all XPath querys (namespace-uri, etc)\" if ie?(session)\n        session.visit '/with_html5_svg'\n        rect = session.find(:css, 'div svg rect:first-of-type')\n        expect(rect.path).to eq(\"/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]\")\n        expect(session.find(:xpath, rect.path)).to eq rect\n      end\n\n      it 'handles case sensitive element names' do\n        pending \"IE 11 doesn't handle all XPath querys (namespace-uri, etc)\" if ie?(session)\n        session.visit '/with_namespace'\n        els = session.all(:css, 'div *', visible: :all)\n        expect { els.map(&:path) }.not_to raise_error\n        lg = session.find(:css, 'div linearGradient', visible: :all)\n        expect(session.find(:xpath, lg.path, visible: :all)).to eq lg\n      end\n    end\n\n    describe 'all with disappearing elements' do\n      it 'ignores stale elements in results' do\n        session.visit('/path')\n        elements = session.all(:link) { |_node| raise Selenium::WebDriver::Error::StaleElementReferenceError }\n        expect(elements.size).to eq 0\n      end\n    end\n\n    describe '#evaluate_script' do\n      it 'can return an element' do\n        session.visit('/form')\n        element = session.evaluate_script(\"document.getElementById('form_title')\")\n        expect(element).to eq session.find(:id, 'form_title')\n      end\n\n      it 'returns a shadow root' do\n        session.visit('/with_shadow')\n        shadow = session.find(:css, '#shadow_host')\n        element = session.evaluate_script('arguments[0].shadowRoot', shadow)\n        expect(element).to be_instance_of(Capybara::Node::Element)\n      end\n\n      it 'can return arrays of nested elements' do\n        session.visit('/form')\n        elements = session.evaluate_script('document.querySelectorAll(\"#form_city option\")')\n        expect(elements).to all(be_instance_of Capybara::Node::Element)\n        expect(elements).to eq session.find(:css, '#form_city').all(:css, 'option').to_a\n      end\n\n      it 'can return hashes with elements' do\n        session.visit('/form')\n        result = session.evaluate_script(\"{ a: document.getElementById('form_title'), b: {c: document.querySelectorAll('#form_city option')}}\")\n        expect(result).to eq(\n          'a' => session.find(:id, 'form_title'),\n          'b' => {\n            'c' => session.find(:css, '#form_city').all(:css, 'option').to_a\n          }\n        )\n      end\n\n      describe '#evaluate_async_script' do\n        it 'will timeout if the script takes too long' do\n          skip 'safaridriver returns the wrong error type' if safari?(session)\n          session.visit('/with_js')\n          expect do\n            session.using_wait_time(1) do\n              session.evaluate_async_script('var cb = arguments[0]; setTimeout(function(){ cb(null) }, 3000)')\n            end\n          end.to raise_error Selenium::WebDriver::Error::ScriptTimeoutError\n        end\n      end\n    end\n\n    describe 'Element#inspect' do\n      it 'outputs obsolete elements' do\n        session.visit('/form')\n        el = session.find(:button, 'Click me!').click\n        expect(session).to have_no_button('Click me!')\n        allow(el).to receive(:synchronize)\n        expect(el.inspect).to eq 'Obsolete #<Capybara::Node::Element>'\n        expect(el).not_to have_received(:synchronize)\n      end\n    end\n\n    describe 'Element#click' do\n      it 'should handle fixed headers/footers' do\n        session.visit('/with_fixed_header_footer')\n        session.using_wait_time(2) do\n          session.find(:link, 'Go to root').click\n        end\n        expect(session).to have_current_path('/')\n      end\n    end\n\n    describe 'Capybara#Node#attach_file' do\n      it 'can attach a directory' do\n        pending \"Geckodriver doesn't support uploading a directory\" if firefox?(session)\n        pending \"Selenium remote doesn't support transferring a directory\" if remote?(session)\n        pending \"Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary\" if chrome?(session) && chrome_lt?(110, session) && ENV.fetch('HEADLESS', nil)\n        pending \"IE doesn't support uploading a directory\" if ie?(session)\n        pending 'Chrome/chromedriver 73 breaks this' if chrome?(session) && chrome_gte?(73, session) && chrome_lt?(75, session)\n\n        session.visit('/form')\n        test_file_dir = File.expand_path('./fixtures', File.dirname(__FILE__))\n        session.attach_file('Directory Upload', test_file_dir)\n        session.click_button('Upload Multiple')\n        expect(session).to have_text('5 | ') # number of files\n      end\n\n      it 'can attach a relative file' do\n        pending 'Geckdoriver on windows requires alternate file separator which path expansion replaces' if Gem.win_platform? && firefox?(session)\n\n        session.visit('/form')\n        session.attach_file('Single Document', 'spec/fixtures/capybara.csv')\n        session.click_button('Upload Single')\n        expect(session).to have_text('Content-type: text/csv')\n      end\n    end\n\n    context 'Windows' do\n      it \"can't close the primary window\" do\n        expect do\n          session.current_window.close\n        end.to raise_error(ArgumentError, 'Not allowed to close the primary window')\n      end\n    end\n\n    # rubocop:disable RSpec/InstanceVariable\n    describe 'Capybara#disable_animation' do\n      context 'when set to `true`' do\n        before(:context) do # rubocop:disable RSpec/BeforeAfterAll\n          skip \"Safari doesn't support multiple sessions\" if safari?(session)\n          # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,\n          # it doesn't affect any of these tests because the settings are applied per-session\n          Capybara.disable_animation = true\n          @animation_session = Capybara::Session.new(session.mode, TestApp.new)\n        end\n\n        it 'should add CSS to the <head> element' do\n          @animation_session.visit('with_animation')\n\n          expect(@animation_session).to have_selector(:css, 'head > style', text: 'transition: none', visible: :hidden)\n        end\n\n        it 'should disable CSS transitions' do\n          @animation_session.visit('with_animation')\n          @animation_session.click_link('transition me away')\n          expect(@animation_session).to have_no_link('transition me away', wait: 0.5)\n        end\n\n        it 'should disable CSS animations (set to 0s)' do\n          @animation_session.visit('with_animation')\n          sleep 1\n          @animation_session.click_link('animate me away')\n          expect(@animation_session).to have_no_link('animate me away', wait: 0.5)\n        end\n\n        it 'should disable CSS animations on pseudo elements (set to 0s)' do\n          @animation_session.visit('with_animation')\n          sleep 1\n          @animation_session.find_link('animate me away').right_click\n          expect(@animation_session).to have_content('Animation Ended', wait: 0.1)\n        end\n\n        it 'should scroll the page instantly', requires: [:js] do\n          @animation_session.visit('with_animation')\n          scroll_y = @animation_session.evaluate_script(<<~JS)\n            (function(){\n              window.scrollTo(0,500);\n              return window.scrollY;\n            })()\n          JS\n          expect(scroll_y).to eq 500\n        end\n\n        it 'should scroll the page instantly without jquery animation', requires: [:js] do\n          @animation_session.visit('with_jquery_animation')\n          @animation_session.click_link('scroll top 500')\n          scroll_y = @animation_session.evaluate_script('window.scrollY')\n          expect(scroll_y).to eq 500\n        end\n      end\n\n      context 'when set to `false`' do\n        before(:context) do # rubocop:disable RSpec/BeforeAfterAll\n          skip \"Safari doesn't support multiple sessions\" if safari?(session)\n          # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,\n          # it doesn't affect any of these tests because the settings are applied per-session\n          Capybara.disable_animation = false\n          @animation_session = Capybara::Session.new(session.mode, TestApp.new)\n        end\n\n        it 'should scroll the page with a smooth animation', requires: [:js] do\n          @animation_session.visit('with_animation')\n          scroll_y = @animation_session.evaluate_script(<<~JS)\n            (function(){\n              window.scrollTo(0,500);\n              return window.scrollY;\n            })()\n          JS\n          # measured over 0.5 seconds: 0, 75, 282, 478, 500\n          expect(scroll_y).to be < 500\n        end\n\n        it 'should scroll the page with jquery animation', requires: [:js] do\n          @animation_session.visit('with_jquery_animation')\n          @animation_session.click_link('scroll top 500')\n          scroll_y = @animation_session.evaluate_script('window.scrollY')\n          expect(scroll_y).to be < 500\n        end\n      end\n\n      context 'if we pass in css that matches elements' do\n        before(:context) do # rubocop:disable RSpec/BeforeAfterAll\n          skip \"safaridriver doesn't support multiple sessions\" if safari?(session)\n          # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,\n          # it doesn't affect any of these tests because the settings are applied per-session\n          Capybara.disable_animation = '#with_animation a'\n          @animation_session_with_matching_css = Capybara::Session.new(session.mode, TestApp.new)\n        end\n\n        it 'should disable CSS transitions' do\n          @animation_session_with_matching_css.visit('with_animation')\n          sleep 1\n          @animation_session_with_matching_css.click_link('transition me away')\n          expect(@animation_session_with_matching_css).to have_no_link('transition me away', wait: 0.5)\n        end\n\n        it 'should disable CSS animations' do\n          @animation_session_with_matching_css.visit('with_animation')\n          sleep 1\n          @animation_session_with_matching_css.click_link('animate me away')\n          expect(@animation_session_with_matching_css).to have_no_link('animate me away', wait: 0.5)\n        end\n      end\n\n      context 'if we pass in css that does not match elements' do\n        before(:context) do # rubocop:disable RSpec/BeforeAfterAll\n          skip \"Safari doesn't support multiple sessions\" if safari?(session)\n          # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,\n          # it doesn't affect any of these tests because the settings are applied per-session\n          Capybara.disable_animation = '.this-class-matches-nothing'\n          @animation_session_without_matching_css = Capybara::Session.new(session.mode, TestApp.new)\n        end\n\n        it 'should not disable CSS transitions' do\n          @animation_session_without_matching_css.visit('with_animation')\n          sleep 1\n          @animation_session_without_matching_css.click_link('transition me away')\n          sleep 0.5 # Wait long enough for click to have been processed\n          expect(@animation_session_without_matching_css).to have_link('transition me away', wait: false)\n          expect(@animation_session_without_matching_css).to have_no_link('transition me away', wait: 5)\n        end\n\n        it 'should not disable CSS animations' do\n          @animation_session_without_matching_css.visit('with_animation')\n          sleep 1\n          @animation_session_without_matching_css.click_link('animate me away')\n          sleep 0.5 # Wait long enough for click to have been processed\n          expect(@animation_session_without_matching_css).to have_link('animate me away', wait: false)\n          expect(@animation_session_without_matching_css).to have_no_link('animate me away', wait: 5)\n        end\n      end\n    end\n    # rubocop:enable RSpec/InstanceVariable\n\n    describe ':element selector' do\n      it 'can find html5 svg elements' do\n        session.visit('with_html5_svg')\n        expect(session).to have_selector(:element, :svg)\n        expect(session).to have_selector(:element, :rect, visible: :visible)\n        expect(session).to have_selector(:element, :circle)\n        expect(session).to have_selector(:element, :linearGradient, visible: :all)\n      end\n\n      it 'can query attributes with strange characters' do\n        session.visit('/form')\n        expect(session).to have_selector(:element, '{custom}': true)\n        expect(session).to have_selector(:element, '{custom}': 'abcdef')\n      end\n    end\n\n    describe 'with react' do\n      context 'controlled components' do\n        it 'can set and clear a text field' do\n          skip \"This test doesn't support older browsers\" if ie?(session)\n\n          session.visit 'react'\n          session.fill_in('Name:', with: 'abc')\n          session.accept_prompt 'A name was submitted: abc' do\n            session.click_button('Submit')\n          end\n\n          session.fill_in('Name:', with: '')\n          session.accept_prompt(/A name was submitted: $/) do\n            session.click_button('Submit')\n          end\n        end\n\n        it 'works with rapid fill' do\n          skip \"This test doesn't support older browsers\" if ie?(session)\n\n          session.visit 'react'\n          long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join\n\n          session.fill_in('Name:', with: long_string)\n          session.accept_prompt \"A name was submitted: #{long_string}\" do\n            session.click_button('Submit')\n          end\n        end\n      end\n    end\n  end\n\n  def headless_or_remote?\n    !ENV['HEADLESS'].nil? || session.driver.options[:browser] == :remote\n  end\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rspec/expectations'\nrequire 'selenium_statistics'\nif ENV['TRAVIS']\n  require 'coveralls'\n  Coveralls.wear! do\n    add_filter '/lib/capybara/driver/'\n    add_filter '/lib/capybara/registrations/'\n  end\nend\nrequire 'capybara/spec/spec_helper'\n\nmodule Capybara\n  module SpecHelper\n    def firefox?(session)\n      browser_name(session) == :firefox &&\n        ((defined?(::Selenium::WebDriver::VERSION) && (Gem::Version.new(::Selenium::WebDriver::VERSION) >= Gem::Version.new('4'))) ||\n         session.driver.browser.capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities))\n    end\n\n    def firefox_lt?(version, session)\n      firefox?(session) && (session.driver.browser.capabilities[:browser_version].to_f < version)\n    end\n\n    def firefox_gte?(version, session)\n      firefox?(session) && (session.driver.browser.capabilities[:browser_version].to_f >= version)\n    end\n\n    def geckodriver_version(session)\n      Gem::Version.new(session.driver.browser.capabilities['moz:geckodriverVersion'])\n    end\n\n    def geckodriver_gte?(version, session)\n      firefox?(session) && geckodriver_version(session) >= Gem::Version.new(version)\n    end\n\n    def geckodriver_lt?(version, session)\n      firefox?(session) && geckodriver_version(session) < Gem::Version.new(version)\n    end\n\n    def chrome?(session)\n      browser_name(session) == :chrome\n    end\n\n    def chrome_version(session)\n      (session.driver.browser.capabilities[:browser_version] ||\n        session.driver.browser.capabilities[:version]).to_f\n    end\n\n    def chrome_lt?(version, session)\n      chrome?(session) && (chrome_version(session) < version)\n    end\n\n    def chrome_gte?(version, session)\n      chrome?(session) && (chrome_version(session) >= version)\n    end\n\n    def chromedriver_version(session)\n      Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])\n    end\n\n    def chromedriver_gte?(version, session)\n      chrome?(session) && chromedriver_version(session) >= Gem::Version.new(version)\n    end\n\n    def chromedriver_lt?(version, session)\n      chrome?(session) && chromedriver_version(session) < Gem::Version.new(version)\n    end\n\n    def selenium?(session)\n      session.driver.is_a? Capybara::Selenium::Driver\n    end\n\n    def selenium_lt?(version, session)\n      selenium?(session) &&\n        Gem::Version.new(::Selenium::WebDriver::VERSION) < Gem::Version.new(version)\n    end\n\n    def edge?(session)\n      browser_name(session).to_s.start_with?('edge')\n    end\n\n    def legacy_edge?(session)\n      browser_name(session) == :edge\n    end\n\n    def edge_lt?(version, session)\n      edge?(session) && (chrome_version(session) < version)\n    end\n\n    def edge_gte?(version, session)\n      edge?(session) && (chrome_version(session) >= version)\n    end\n\n    def ie?(session)\n      %i[internet_explorer ie].include?(browser_name(session))\n    end\n\n    def safari?(session)\n      %i[safari Safari Safari_Technology_Preview].include?(browser_name(session))\n    end\n\n    def browser_name(session)\n      session.driver.browser.browser if session.respond_to?(:driver)\n    end\n\n    def remote?(session)\n      session.driver.browser.is_a? ::Selenium::WebDriver::Remote::Driver\n    end\n\n    def self.log_selenium_driver_version(mod)\n      mod = mod::Service if ::Selenium::WebDriver::Service.respond_to? :driver_path\n      path = mod.driver_path\n      path = path.call if path.respond_to? :call\n      $stdout.puts `#{path.gsub(' ', '\\ ')} --version` if path\n    end\n  end\nend\n\nRSpec.configure do |config|\n  Capybara::SpecHelper.configure(config)\n  config.expect_with :rspec do |expectations|\n    expectations.syntax = :expect\n  end\n  config.mock_with :rspec do |mocks|\n    mocks.verify_partial_doubles = true\n  end\n  config.filter_run_including focus_: true unless ENV['CI']\n  config.run_all_when_everything_filtered = true\n  config.after(:suite) { SeleniumStatistics.print_results }\nend\n"
  },
  {
    "path": "spec/whitespace_normalizer_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'capybara/node/whitespace_normalizer'\n\nRSpec.describe Capybara::Node::WhitespaceNormalizer do\n  subject(:normalizer) do\n    klass = Class.new do\n      include Capybara::Node::WhitespaceNormalizer\n    end\n\n    klass.new\n  end\n\n  let(:text_needing_correction) do\n    <<~TEXT\n      Some     #{described_class::NON_BREAKING_SPACE}text\n      #{described_class::RIGHT_TO_LEFT_MARK}\n      #{described_class::ZERO_WIDTH_SPACE * 30}\n      #{described_class::LEFT_TO_RIGHT_MARK}\n      Here\n    TEXT\n  end\n\n  describe '#normalize_spacing' do\n    it 'does nothing to text not containing special characters' do\n      expect(normalizer.normalize_spacing('text')).to eq('text')\n    end\n\n    it 'compresses excess breaking spacing' do\n      expect(\n        normalizer.normalize_spacing(text_needing_correction)\n      ).to eq('Some  text Here')\n    end\n  end\n\n  describe '#normalize_visible_spacing' do\n    it 'does nothing to text not containing special characters' do\n      expect(normalizer.normalize_visible_spacing('text')).to eq('text')\n    end\n\n    it 'compresses excess breaking visible spacing' do\n      expect(\n        normalizer.normalize_visible_spacing(text_needing_correction)\n      ).to eq <<~TEXT.chomp\n        Some  text\n        #{described_class::RIGHT_TO_LEFT_MARK}\n        #{described_class::ZERO_WIDTH_SPACE * 30}\n        #{described_class::LEFT_TO_RIGHT_MARK}\n        Here\n      TEXT\n    end\n  end\nend\n"
  },
  {
    "path": "spec/xpath_builder_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\n# rubocop:disable RSpec/InstanceVariable\nRSpec.describe Capybara::Selector::XPathBuilder do\n  let :builder do\n    described_class.new(@xpath)\n  end\n\n  context 'add_attribute_conditions' do\n    it 'adds a single string condition to a single selector' do\n      @xpath = './/div'\n      selector = builder.add_attribute_conditions(random: 'abc')\n      expect(selector).to eq %((.//div)[(./@random = 'abc')])\n    end\n\n    it 'adds multiple string conditions to a single selector' do\n      @xpath = './/div'\n      selector = builder.add_attribute_conditions(random: 'abc', other: 'def')\n      expect(selector).to eq %(((.//div)[(./@random = 'abc')])[(./@other = 'def')])\n    end\n\n    it 'adds a single string condition to a multiple selector' do\n      @xpath = XPath.descendant(:div, :ul)\n      selector = builder.add_attribute_conditions(random: 'abc')\n      expect(selector.to_s).to eq @xpath[XPath.attr(:random) == 'abc'].to_s\n    end\n\n    it 'adds multiple string conditions to a multiple selector' do\n      @xpath = XPath.descendant(:div, :ul)\n      selector = builder.add_attribute_conditions(random: 'abc', other: 'def')\n      expect(selector.to_s).to eq %(.//*[self::div | self::ul][(./@random = 'abc')][(./@other = 'def')])\n    end\n\n    it 'adds simple regexp conditions to a single selector' do\n      @xpath = XPath.descendant(:div)\n      selector = builder.add_attribute_conditions(random: /abc/, other: /def/)\n      expect(selector.to_s).to eq %(.//div[./@random[contains(., 'abc')]][./@other[contains(., 'def')]])\n    end\n\n    it 'adds wildcard regexp conditions to a single selector' do\n      @xpath = './/div'\n      selector = builder.add_attribute_conditions(random: /abc.*def/, other: /def.*ghi/)\n      expect(selector).to eq %(((.//div)[./@random[(contains(., 'abc') and contains(., 'def'))]])[./@other[(contains(., 'def') and contains(., 'ghi'))]])\n    end\n\n    it 'adds alternated regexp conditions to a single selector' do\n      @xpath = XPath.descendant(:div)\n      selector = builder.add_attribute_conditions(random: /abc|def/, other: /def|ghi/)\n      expect(selector.to_s).to eq %(.//div[./@random[(contains(., 'abc') or contains(., 'def'))]][./@other[(contains(., 'def') or contains(., 'ghi'))]])\n    end\n\n    it 'adds alternated regexp conditions to a multiple selector' do\n      @xpath = XPath.descendant(:div, :ul)\n      selector = builder.add_attribute_conditions(other: /def.*ghi|jkl/)\n      expect(selector.to_s).to eq %(.//*[self::div | self::ul][./@other[((contains(., 'def') and contains(., 'ghi')) or contains(., 'jkl'))]])\n    end\n\n    it \"returns original selector when regexp can't be substringed\" do\n      @xpath = './/div'\n      selector = builder.add_attribute_conditions(other: /.+/)\n      expect(selector).to eq '(.//div)[./@other]'\n    end\n\n    context ':class' do\n      it 'handles string' do\n        @xpath = './/a'\n        selector = builder.add_attribute_conditions(class: 'my_class')\n        expect(selector).to eq %((.//a)[contains(concat(' ', normalize-space(./@class), ' '), ' my_class ')])\n      end\n\n      it 'handles negated strings' do\n        @xpath = XPath.descendant(:a)\n        selector = builder.add_attribute_conditions(class: '!my_class')\n        expect(selector.to_s).to eq @xpath[!XPath.attr(:class).contains_word('my_class')].to_s\n      end\n\n      it 'handles array of strings' do\n        @xpath = './/a'\n        selector = builder.add_attribute_conditions(class: %w[my_class my_other_class])\n        expect(selector).to eq %((.//a)[(contains(concat(' ', normalize-space(./@class), ' '), ' my_class ') and contains(concat(' ', normalize-space(./@class), ' '), ' my_other_class '))])\n      end\n\n      it 'handles array of string when negated included' do\n        @xpath = XPath.descendant(:a)\n        selector = builder.add_attribute_conditions(class: %w[my_class !my_other_class])\n        expect(selector.to_s).to eq @xpath[XPath.attr(:class).contains_word('my_class') & !XPath.attr(:class).contains_word('my_other_class')].to_s\n      end\n    end\n  end\nend\n# rubocop:enable RSpec/InstanceVariable\n"
  }
]