From 87914daaed45457afd5369aa347494ec3213018d Mon Sep 17 00:00:00 2001 From: dblock Date: Sun, 20 Oct 2024 09:28:00 -0400 Subject: [PATCH] Upgraded to Ruby 3.3.5. --- .github/workflows/rubocop.yml | 2 +- .github/workflows/test.yml | 28 +- .rubocop.yml | 7 + .rubocop_todo.yml | 113 +++++- Gemfile | 19 +- Gemfile.lock | 340 ++++++++++-------- .../api/helpers/cursor_helpers.rb | 10 +- .../api/helpers/error_helpers.rb | 42 +-- .../api/helpers/sort_helpers.rb | 6 +- spec/api/cors_spec.rb | 2 + spec/api/endpoints/root_endpoint_spec.rb | 4 +- spec/api/endpoints/status_endpoint_spec.rb | 2 + spec/api/endpoints/teams_endpoint_spec.rb | 24 +- spec/api/swagger_documentation_spec.rb | 2 + spec/initializers/shellwords_spec.rb | 15 +- spec/integration/teams_spec.rb | 9 +- spec/models/team_spec.rb | 17 +- .../commands/default_spec.rb | 2 + .../slack-api-explorer/commands/slack_spec.rb | 21 +- .../commands/unknown_spec.rb | 4 +- spec/slack-api-explorer/version_spec.rb | 2 +- spec/support/api/endpoints/endpoint_test.rb | 4 +- .../endpoints/it_behaves_like_a_cursor_api.rb | 19 +- spec/support/database_cleaner.rb | 8 +- 24 files changed, 450 insertions(+), 252 deletions(-) diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index 8330afa..a8cf9be 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: "2.7.7" + ruby-version: "3.3.5" bundler-cache: true - name: Run RuboCop run: bundle exec rubocop diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 123b5d0..43c961c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,22 +6,22 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: browser-actions/setup-firefox@latest - with: - firefox-version: "108.0" - - uses: browser-actions/setup-geckodriver@latest - with: - geckodriver-version: "0.32.0" + - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: - ruby-version: "2.7.7" - bundler-cache: true + ruby-version: "3.3.5" - uses: supercharge/mongodb-github-action@1.7.0 with: - mongodb-version: "5" - mongodb-db: slack_api_explorer_test - - name: Run tests - uses: GabrielBB/xvfb-action@v1 + mongodb-version: "7.0" + - uses: browser-actions/setup-geckodriver@latest + with: + geckodriver-version: "0.34.0" + - uses: browser-actions/setup-firefox@v1 + with: + firefox-version: "129.0.2" + - run: | + bundle install + - uses: GabrielBB/xvfb-action@v1 with: - run: bundle exec rake + run: | + bundle exec rake spec diff --git a/.rubocop.yml b/.rubocop.yml index bab0179..6eb3025 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,6 @@ AllCops: + NewCops: enable + TargetRubyVersion: 3.3 Exclude: - vendor/**/* - bin/**/* @@ -10,3 +12,8 @@ Metrics: Enabled: false inherit_from: .rubocop_todo.yml + +require: + - rubocop-capybara + - rubocop-rake + - rubocop-rspec \ No newline at end of file diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4dd6e56..e4c27ba 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,22 +1,127 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2019-04-16 08:56:55 -0400 using RuboCop version 0.67.2. +# on 2024-10-20 13:24:03 UTC using RuboCop version 1.67.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# CheckDefinitionPathHierarchyRoots: lib, spec, test, src # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS Naming/FileName: Exclude: + - 'Rakefile.rb' - 'slack-api-explorer.rb' # Offense count: 2 -# Configuration parameters: Blacklist. -# Blacklist: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +# Configuration parameters: ForbiddenDelimiters. +# ForbiddenDelimiters: (?i-mx:(^|\s)(EO[A-Z]{1}|END)(\s|$)) Naming/HeredocDelimiterNaming: Exclude: - 'slack-api-explorer/commands/help.rb' - 'slack-api-explorer/info.rb' + +# Offense count: 6 +RSpec/AnyInstance: + Exclude: + - 'spec/api/endpoints/status_endpoint_spec.rb' + - 'spec/api/endpoints/teams_endpoint_spec.rb' + - 'spec/integration/teams_spec.rb' + +# Offense count: 17 +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Exclude: + - 'spec/api/404_spec.rb' + - 'spec/api/cors_spec.rb' + - 'spec/api/endpoints/status_endpoint_spec.rb' + - 'spec/api/endpoints/teams_endpoint_spec.rb' + - 'spec/api/swagger_documentation_spec.rb' + - 'spec/integration/teams_spec.rb' + - 'spec/slack-api-explorer/commands/slack_spec.rb' + - 'spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb' + +# Offense count: 10 +# Configuration parameters: CountAsOne. +RSpec/ExampleLength: + Max: 27 + +# Offense count: 1 +# Configuration parameters: AssignmentOnly. +RSpec/InstanceVariable: + Exclude: + - 'spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb' + +# Offense count: 5 +RSpec/LetSetup: + Exclude: + - 'spec/api/endpoints/status_endpoint_spec.rb' + - 'spec/api/endpoints/teams_endpoint_spec.rb' + +# Offense count: 13 +# Configuration parameters: . +# SupportedStyles: have_received, receive +RSpec/MessageSpies: + EnforcedStyle: receive + +# Offense count: 28 +RSpec/MultipleExpectations: + Max: 7 + +# Offense count: 2 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only +RSpec/NamedSubject: + Exclude: + - 'spec/api/swagger_documentation_spec.rb' + +# Offense count: 1 +# Configuration parameters: AllowedGroups. +RSpec/NestedGroups: + Max: 4 + +# Offense count: 2 +RSpec/RepeatedExampleGroupDescription: + Exclude: + - 'spec/api/endpoints/teams_endpoint_spec.rb' + +# Offense count: 8 +# Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata. +# Include: **/*_spec.rb +RSpec/SpecFilePathFormat: + Exclude: + - '**/spec/routing/**/*' + - 'spec/api/404_spec.rb' + - 'spec/api/cors_spec.rb' + - 'spec/api/robots_spec.rb' + - 'spec/api/swagger_documentation_spec.rb' + - 'spec/slack-api-explorer/commands/default_spec.rb' + - 'spec/slack-api-explorer/commands/slack_spec.rb' + - 'spec/slack-api-explorer/commands/unknown_spec.rb' + - 'spec/slack-api-explorer/version_spec.rb' + +# Offense count: 1 +RSpec/StubbedMock: + Exclude: + - 'spec/api/endpoints/teams_endpoint_spec.rb' + +# Offense count: 2 +# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. +RSpec/VerifiedDoubles: + Exclude: + - 'spec/api/endpoints/teams_endpoint_spec.rb' + +# Offense count: 1 +RSpec/VoidExpect: + Exclude: + - 'spec/integration/teams_spec.rb' + +# Offense count: 15 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 175 diff --git a/Gemfile b/Gemfile index 2849847..f6578ea 100644 --- a/Gemfile +++ b/Gemfile @@ -1,19 +1,17 @@ source 'http://rubygems.org' -ruby '2.7.7' +ruby '3.3.5' -gem 'giphy' gem 'irb' gem 'jsonpath', '0.9.0' gem 'kaminari-grape' gem 'mongoid' gem 'mongoid-scroll' -gem 'newrelic-slack-ruby-bot' gem 'newrelic_rpm' -gem 'rack', '~> 2.2' +gem 'newrelic-slack-ruby-bot' +gem 'rack' gem 'rack-robotz' gem 'rack-server-pages' -gem 'slack-ruby-bot-server' gem 'slack-ruby-bot-server-mailchimp' gem 'slack-ruby-bot-server-rtm' gem 'unicorn' @@ -21,7 +19,10 @@ gem 'unicorn' group :development, :test do gem 'foreman' gem 'rake' - gem 'rubocop', '0.76.0' + gem 'rubocop' + gem 'rubocop-capybara' + gem 'rubocop-rake' + gem 'rubocop-rspec' end group :development do @@ -30,11 +31,13 @@ end group :test do gem 'capybara' - gem 'database_cleaner', '~> 1.8.4' + gem 'database_cleaner-mongoid' gem 'fabrication' gem 'faker' - gem 'hyperclient', '~> 0.9' + gem 'faraday-rack' + gem 'hyperclient' gem 'rack-test' + gem 'rackup' gem 'rspec' gem 'selenium-webdriver' gem 'vcr' diff --git a/Gemfile.lock b/Gemfile.lock index 15de972..1fe7795 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,115 +1,132 @@ GEM remote: http://rubygems.org/ specs: - activemodel (7.0.4.2) - activesupport (= 7.0.4.2) - activesupport (7.0.4.2) - concurrent-ruby (~> 1.0, >= 1.0.2) + activemodel (7.2.1.1) + activesupport (= 7.2.1.1) + activesupport (7.2.1.1) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - tzinfo (~> 2.0) - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) ast (2.4.2) - async (1.31.0) - console (~> 1.10) - nio4r (~> 2.3) - timers (~> 4.1) - async-io (1.34.3) + async (2.17.0) + console (~> 1.26) + fiber-annotation + io-event (~> 1.6, >= 1.6.5) + async-io (1.43.2) async async-websocket (0.8.0) async-io websocket-driver (~> 0.7.0) - bson (4.15.0) - builder (3.2.4) - capybara (3.38.0) + base64 (0.2.0) + bigdecimal (3.1.8) + bson (5.0.1) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - concurrent-ruby (1.2.2) - console (1.16.2) - fiber-local - crack (0.4.5) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) + console (1.27.0) + fiber-annotation + fiber-local (~> 1.1) + json + crack (1.0.0) + bigdecimal rexml - database_cleaner (1.8.5) + database_cleaner-core (2.0.1) + database_cleaner-mongoid (2.0.1) + database_cleaner-core (~> 2.0.0) + mongoid declarative (0.0.20) - diff-lcs (1.5.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) - dry-core (1.0.0) + diff-lcs (1.5.1) + domain_name (0.6.20240107) + drb (2.2.1) + dry-core (1.0.1) concurrent-ruby (~> 1.0) zeitwerk (~> 2.6) - dry-inflector (1.0.0) + dry-inflector (1.1.0) dry-logic (1.5.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0, < 2) zeitwerk (~> 2.6) - dry-types (1.7.1) + dry-types (1.7.2) + bigdecimal (~> 3.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0) dry-inflector (~> 1.0) dry-logic (~> 1.4) zeitwerk (~> 2.6) - fabrication (2.30.0) - faker (3.1.1) + fabrication (2.31.0) + faker (3.5.1) i18n (>= 1.8.11, < 2) - faraday (0.17.6) - multipart-post (>= 1.2, < 3) - faraday-digestauth (0.4.1) - faraday (>= 0.7) - net-http-digest_auth (~> 1.4) - faraday_hal_middleware (0.1.1) - faraday_middleware (>= 0.9) - faraday_middleware (0.14.0) - faraday (>= 0.7.4, < 1.0) - faraday_middleware-parse_oj (0.3.2) - faraday (~> 0.9) - faraday_middleware (>= 0.9.1, < 1.0) - oj (>= 2.0, < 4.0) - fiber-local (1.0.0) - foreman (0.87.2) - giphy (3.0.0) - faraday (~> 0.9) - faraday_middleware (~> 0.9) - faraday_middleware-parse_oj (~> 0.3) - launchy (~> 2.4) - gli (2.21.0) - grape (1.7.0) - activesupport - builder + faraday (2.12.0) + faraday-net_http (>= 2.0, < 3.4) + json + logger + faraday-follow_redirects (0.3.0) + faraday (>= 1, < 3) + faraday-mashify (0.1.1) + faraday (~> 2.0) + hashie + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (3.3.0) + net-http + faraday-rack (2.0.0) + faraday (~> 2.0) + faraday_hal_middleware (0.2.0) + faraday (~> 2.0) + fiber-annotation (0.2.0) + fiber-local (1.1.0) + fiber-storage + fiber-storage (1.0.0) + foreman (0.88.1) + gli (2.21.5) + grape (2.2.0) + activesupport (>= 6) dry-types (>= 1.1) - mustermann-grape (~> 1.0.0) - rack (>= 1.3.0) - rack-accept + mustermann-grape (~> 1.1.0) + rack (>= 2) + zeitwerk grape-roar (0.4.1) grape multi_json roar (~> 1.1.0) - grape-swagger (1.5.0) - grape (~> 1.3) - hashdiff (1.0.1) + grape-swagger (2.1.1) + grape (>= 1.7, < 3.0) + rack-test (~> 2) + hashdiff (1.1.1) hashie (5.0.0) http-accept (1.7.0) - http-cookie (1.0.5) + http-cookie (1.0.7) domain_name (~> 0.5) - hyperclient (0.9.3) + hyperclient (2.0.0) addressable - faraday (>= 0.9.0) - faraday-digestauth (>= 0.3.0) - faraday_hal_middleware - faraday_middleware - net-http-digest_auth - i18n (1.12.0) + faraday (>= 2) + faraday-follow_redirects + faraday_hal_middleware (>= 0.2) + i18n (1.14.6) concurrent-ruby (~> 1.0) - io-console (0.6.0) - irb (1.6.3) - reline (>= 0.3.0) - jaro_winkler (1.5.4) + io-console (0.7.2) + io-event (1.7.2) + irb (1.14.1) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.7.2) jsonpath (0.9.0) multi_json to_regexp (~> 0.2.1) @@ -118,73 +135,78 @@ GEM grape kaminari-core (~> 1.0) kgio (2.11.4) - launchy (2.5.2) - addressable (~> 2.8) + language_server-protocol (3.17.0.3) + logger (1.6.1) mailchimp_api_v3 (0.2.18) rest-client (~> 2) matrix (0.4.2) - mime-types (3.4.1) + mime-types (3.6.0) + logger mime-types-data (~> 3.2015) - mime-types-data (3.2023.0218.1) - mini_mime (1.1.2) - mini_portile2 (2.8.1) - minitest (5.18.0) - mongo (2.18.2) - bson (>= 4.14.1, < 5.0.0) - mongoid (8.0.3) - activemodel (>= 5.1, < 7.1, != 7.0.0) + mime-types-data (3.2024.1001) + mini_mime (1.1.5) + mini_portile2 (2.8.7) + minitest (5.25.1) + mongo (2.21.0) + bson (>= 4.14.1, < 6.0.0) + mongoid (9.0.2) + activemodel (>= 5.1, < 7.3, != 7.0.0) + concurrent-ruby (>= 1.0.5, < 2.0) mongo (>= 2.18.0, < 3.0.0) - ruby2_keywords (~> 0.0.5) - mongoid-compatibility (0.6.0) + mongoid-compatibility (1.0.0) activesupport mongoid (>= 2.0) - mongoid-scroll (1.0.0) + mongoid-scroll (2.0.0) i18n - mongoid (>= 3.0) - mongoid-compatibility + mongoid (>= 6.0) mongoid-shell (0.4.6) i18n mongoid (>= 3.0.0) mongoid-compatibility multi_json (1.15.0) - multipart-post (2.3.0) - mustermann (3.0.0) + multipart-post (2.4.1) + mustermann (3.0.3) ruby2_keywords (~> 0.0.1) - mustermann-grape (1.0.2) + mustermann-grape (1.1.0) mustermann (>= 1.0.0) - net-http-digest_auth (1.4.1) + net-http (0.4.1) + uri netrc (0.11.0) newrelic-slack-ruby-bot (0.2.2) newrelic_rpm slack-ruby-bot (>= 0.10.5) - newrelic_rpm (9.0.0) - nio4r (2.5.8) - nokogiri (1.14.2) - mini_portile2 (~> 2.8.0) + newrelic_rpm (9.14.0) + nokogiri (1.16.7) + mini_portile2 (~> 2.8.2) racc (~> 1.4) - oj (3.14.2) - parallel (1.22.1) - parser (3.2.1.1) + parallel (1.26.3) + parser (3.3.5.0) ast (~> 2.4.1) - public_suffix (5.0.1) - racc (1.6.2) - rack (2.2.6.3) - rack-accept (0.4.5) - rack (>= 0.4) - rack-cors (2.0.0) + racc + psych (5.1.2) + stringio + public_suffix (6.0.1) + racc (1.8.1) + rack (3.1.8) + rack-cors (2.0.2) rack (>= 2.0.0) rack-rewrite (1.5.1) rack-robotz (0.0.4) rack - rack-server-pages (0.1.0) + rack-server-pages (0.2.0) rack - rack-test (2.0.2) + rack-test (2.1.0) rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) rainbow (3.1.1) raindrops (0.20.1) - rake (13.0.6) - regexp_parser (2.7.0) - reline (0.3.2) + rake (13.2.1) + rdoc (6.7.0) + psych (>= 4.0.0) + regexp_parser (2.9.2) + reline (0.5.10) io-console (~> 0.5) representable (3.2.0) declarative (< 0.1.0) @@ -195,33 +217,47 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.5) + rexml (3.3.8) roar (1.1.1) representable (~> 3.0) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-core (3.12.1) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.2) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.2) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-mocks (3.12.3) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-support (3.12.0) - rubocop (0.76.0) - jaro_winkler (~> 1.5.1) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.67.0) + json (~> 2.3) + language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 2.6) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.4, < 3.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.32.3) + parser (>= 3.3.1.0) + rubocop-capybara (2.21.0) + rubocop (~> 1.41) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (3.1.0) + rubocop (~> 1.61) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) - selenium-webdriver (4.8.1) + securerandom (0.3.1) + selenium-webdriver (4.25.0) + base64 (~> 0.2) + logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -229,7 +265,7 @@ GEM activesupport hashie slack-ruby-client (>= 0.14.0) - slack-ruby-bot-server (2.1.0) + slack-ruby-bot-server (2.1.1) async foreman grape @@ -240,57 +276,56 @@ GEM rack-rewrite rack-server-pages slack-ruby-client - slack-ruby-bot-server-mailchimp (0.2.0) + slack-ruby-bot-server-mailchimp (0.3.0) mailchimp_api_v3 - slack-ruby-bot-server (>= 0.10.0) + slack-ruby-bot-server (>= 2.0.1) slack-ruby-bot-server-rtm (0.2.0) async-websocket (~> 0.8.0) slack-ruby-bot (>= 0.12.0) slack-ruby-bot-server (>= 1.0.0) - slack-ruby-client (0.14.6) - activesupport - faraday (>= 0.9) - faraday_middleware + slack-ruby-client (2.4.0) + faraday (>= 2.0) + faraday-mashify + faraday-multipart gli hashie - websocket-driver - timers (4.3.5) + stringio (3.1.1) to_regexp (0.2.1) trailblazer-option (0.1.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uber (0.1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) - unicode-display_width (1.6.1) + unicode-display_width (2.6.0) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) - vcr (6.1.0) - webmock (3.18.1) + uri (0.13.1) + vcr (6.3.1) + base64 + webmock (3.24.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - websocket (1.2.9) - websocket-driver (0.7.5) + webrick (1.8.2) + websocket (1.2.11) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.7) + zeitwerk (2.7.1) PLATFORMS ruby DEPENDENCIES capybara - database_cleaner (~> 1.8.4) + database_cleaner-mongoid fabrication faker + faraday-rack foreman - giphy - hyperclient (~> 0.9) + hyperclient irb jsonpath (= 0.9.0) kaminari-grape @@ -299,15 +334,18 @@ DEPENDENCIES mongoid-shell newrelic-slack-ruby-bot newrelic_rpm - rack (~> 2.2) + rack rack-robotz rack-server-pages rack-test + rackup rake rspec - rubocop (= 0.76.0) + rubocop + rubocop-capybara + rubocop-rake + rubocop-rspec selenium-webdriver - slack-ruby-bot-server slack-ruby-bot-server-mailchimp slack-ruby-bot-server-rtm unicorn @@ -315,7 +353,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 2.7.7p221 + ruby 3.3.5p100 BUNDLED WITH 2.4.2 diff --git a/slack-api-explorer/api/helpers/cursor_helpers.rb b/slack-api-explorer/api/helpers/cursor_helpers.rb index c67fe51..f0ab7ee 100644 --- a/slack-api-explorer/api/helpers/cursor_helpers.rb +++ b/slack-api-explorer/api/helpers/cursor_helpers.rb @@ -7,7 +7,7 @@ module CursorHelpers # returns a hash: # results: (paginated collection subset) # next: (cursor to the next page) - def paginate_by_cursor(coll, &_block) + def paginate_by_cursor(coll, &) raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor) results = { results: [], next: nil } @@ -18,18 +18,18 @@ def paginate_by_cursor(coll, &_block) end # some items may be skipped with a block query = block_given? ? coll : coll.limit(size) - query.scroll(params[:cursor]) do |record, next_cursor| + query.scroll(params[:cursor]) do |record, iterator| record = yield(record) if block_given? results[:results] << record if record - results[:next] = next_cursor.to_s + results[:next] = iterator.next_cursor.to_s break if results[:results].count >= size end results[:total_count] = coll.count if params[:total_count] && coll.respond_to?(:count) results end - def paginate_and_sort_by_cursor(coll, options = {}, &block) - Hashie::Mash.new(paginate_by_cursor(sort(coll, options), &block)) + def paginate_and_sort_by_cursor(coll, options = {}, &) + Hashie::Mash.new(paginate_by_cursor(sort(coll, options), &)) end end end diff --git a/slack-api-explorer/api/helpers/error_helpers.rb b/slack-api-explorer/api/helpers/error_helpers.rb index 048d1a1..89bcde8 100644 --- a/slack-api-explorer/api/helpers/error_helpers.rb +++ b/slack-api-explorer/api/helpers/error_helpers.rb @@ -9,40 +9,40 @@ module ErrorHelpers Api::Middleware.logger.error "#{e.class.name}: #{e.message}\n #{backtrace}" error = { type: 'other_error', message: e.message } error[:backtrace] = backtrace - rack_response(error.to_json, 400) + error!(error, 400) end # rescue document validation errors into detail json rescue_from Mongoid::Errors::Validations do |e| backtrace = e.backtrace[0..5].join("\n ") Api::Middleware.logger.warn "#{e.class.name}: #{e.message}\n #{backtrace}" - rack_response({ - type: 'param_error', - message: e.document.errors.full_messages.uniq.join(', ') + '.', - detail: e.document.errors.messages.each_with_object({}) do |(k, v), h| - h[k] = v.uniq - end - }.to_json, 400) + error!({ + type: 'param_error', + message: e.document.errors.full_messages.uniq.join(', ') + '.', + detail: e.document.errors.messages.each_with_object({}) do |(k, v), h| + h[k] = v.uniq + end + }, 400) end rescue_from Grape::Exceptions::Validation do |e| backtrace = e.backtrace[0..5].join("\n ") Api::Middleware.logger.warn "#{e.class.name}: #{e.message}\n #{backtrace}" - rack_response({ - type: 'param_error', - message: 'Invalid parameters.', - detail: { e.params.join(', ') => [e.message] } - }.to_json, 400) + error!({ + type: 'param_error', + message: 'Invalid parameters.', + detail: { e.params.join(', ') => [e.message] } + }, 400) end rescue_from Grape::Exceptions::ValidationErrors do |e| backtrace = e.backtrace[0..5].join("\n ") Api::Middleware.logger.warn "#{e.class.name}: #{e.message}\n #{backtrace}" - rack_response({ - type: 'param_error', - message: 'Invalid parameters.', - detail: e.errors.each_with_object({}) do |(k, v), h| - # JSON does not permit having a key of type Array - h[k.count == 1 ? k.first : k.join(', ')] = v - end - }.to_json, 400) + error!({ + type: 'param_error', + message: 'Invalid parameters.', + detail: e.errors.each_with_object({}) do |(k, v), h| + # JSON does not permit having a key of type Array + h[k.count == 1 ? k.first : k.join(', ')] = v + end + }, 400) end end end diff --git a/slack-api-explorer/api/helpers/sort_helpers.rb b/slack-api-explorer/api/helpers/sort_helpers.rb index 67e3ef9..58383c5 100644 --- a/slack-api-explorer/api/helpers/sort_helpers.rb +++ b/slack-api-explorer/api/helpers/sort_helpers.rb @@ -12,7 +12,9 @@ def sort_order(options = {}) supported_sort_orders = route_sort error!("This API doesn't support sorting", 400) if supported_sort_orders.blank? unless supported_sort_orders.include?(sort_order) - error!("Invalid sort order: #{sort_order}, must be#{supported_sort_orders.count == 1 ? '' : ' one of'} '#{supported_sort_orders.join('\', \'')}'", 400) + error!( + "Invalid sort order: #{sort_order}, must be#{supported_sort_orders.count == 1 ? '' : ' one of'} '#{supported_sort_orders.join('\', \'')}'", 400 + ) end end sort_order = sort_order.split(',').map do |sort_entry| @@ -45,7 +47,7 @@ def sort(coll, options = {}) error!("Cannot sort #{coll.class.name}", 500) end end - coll = coll.is_a?(Module) && coll.respond_to?(:all) ? coll.all : coll + coll.is_a?(Module) && coll.respond_to?(:all) ? coll.all : coll end end end diff --git a/spec/api/cors_spec.rb b/spec/api/cors_spec.rb index c28b888..0f27b71 100644 --- a/spec/api/cors_spec.rb +++ b/spec/api/cors_spec.rb @@ -14,11 +14,13 @@ expect(last_response.headers['Access-Control-Allow-Origin']).to eq '*' expect(last_response.headers['Access-Control-Expose-Headers']).to eq '' end + it 'includes Access-Control-Allow-Origin in the response' do get '/api', {}, 'HTTP_ORIGIN' => '*' expect(last_response.status).to eq 200 expect(last_response.headers['Access-Control-Allow-Origin']).to eq '*' end + it 'includes Access-Control-Allow-Origin in errors' do get '/api/invalid', {}, 'HTTP_ORIGIN' => '*' expect(last_response.status).to eq 404 diff --git a/spec/api/endpoints/root_endpoint_spec.rb b/spec/api/endpoints/root_endpoint_spec.rb index 40e7682..6e29e28 100644 --- a/spec/api/endpoints/root_endpoint_spec.rb +++ b/spec/api/endpoints/root_endpoint_spec.rb @@ -9,6 +9,7 @@ links = JSON.parse(last_response.body)['_links'] expect(links.keys.sort).to eq(%w(self status team teams).sort) end + it 'follows all links' do get '/api' expect(last_response.status).to eq 200 @@ -19,9 +20,10 @@ get href.gsub('http://example.org', '') expect(last_response.status).to eq 200 - expect(JSON.parse(last_response.body)).to_not eq({}) + expect(JSON.parse(last_response.body)).not_to eq({}) end end + it 'rewrites encoded HAL links to make them clickable' do get '/api/teams/%7B?cursor,size%7D' expect(last_response.status).to eq 302 diff --git a/spec/api/endpoints/status_endpoint_spec.rb b/spec/api/endpoints/status_endpoint_spec.rb index 3da7b3f..23c06f4 100644 --- a/spec/api/endpoints/status_endpoint_spec.rb +++ b/spec/api/endpoints/status_endpoint_spec.rb @@ -15,6 +15,7 @@ context 'with an active team' do let!(:team) { Fabricate(:team, active: true) } + it 'returns a status with ping' do status = client.status expect(status.teams_count).to eq 1 @@ -26,6 +27,7 @@ context 'with an inactive team' do let!(:team) { Fabricate(:team, active: false) } + it 'returns no status' do status = client.status expect(status.active_teams_count).to eq 0 diff --git a/spec/api/endpoints/teams_endpoint_spec.rb b/spec/api/endpoints/teams_endpoint_spec.rb index 893fd73..546ab32 100644 --- a/spec/api/endpoints/teams_endpoint_spec.rb +++ b/spec/api/endpoints/teams_endpoint_spec.rb @@ -7,6 +7,7 @@ context 'team' do let(:existing_team) { Fabricate(:team) } + it 'returns a team' do team = client.team(id: existing_team.id) expect(team.id).to eq existing_team.id.to_s @@ -18,19 +19,23 @@ context 'active/inactive' do let!(:active_team) { Fabricate(:team, active: true) } let!(:inactive_team) { Fabricate(:team, active: false) } + it 'returns all teams' do teams = client.teams expect(teams.count).to eq 2 end + it 'returns active teams' do teams = client.teams(active: true) expect(teams.count).to eq 1 expect(teams.to_a.first.team_id).to eq active_team.team_id end end + context 'api true/false' do let!(:team_on) { Fabricate(:team, api: true) } let!(:team_off) { Fabricate(:team, api: false) } + it 'returns teams with api on only' do teams = client.teams expect(teams.count).to eq 1 @@ -40,6 +45,7 @@ context 'team' do let(:existing_team) { Fabricate(:team) } + it 'returns a team' do team = client.team(id: existing_team.id) expect(team.id).to eq existing_team.id.to_s @@ -75,10 +81,12 @@ ) ).and_return(oauth_access) end + after do ENV.delete('SLACK_CLIENT_ID') ENV.delete('SLACK_CLIENT_SECRET') end + it 'creates a team' do expect(SlackRubyBotServer::Service.instance).to receive(:start!) expect do @@ -89,6 +97,7 @@ expect(team.token).to eq 'token' end.to change(Team, :count).by(1) end + it 'reactivates a deactivated team' do expect(SlackRubyBotServer::Service.instance).to receive(:start!) existing_team = Fabricate(:team, token: 'token', active: false) @@ -100,8 +109,9 @@ team = Team.find(team.id) expect(team.token).to eq 'token' expect(team.active).to be true - end.to_not change(Team, :count) + end.not_to change(Team, :count) end + it 'returns a useful error when team already exists' do existing_team = Fabricate(:team, token: 'token') expect { client.teams._post(code: 'code') }.to raise_error Faraday::ClientError do |e| @@ -109,6 +119,7 @@ expect(json['message']).to eq "Team #{existing_team.name} is already registered." end end + it 'reactivates a deactivated team with a different code' do expect(SlackRubyBotServer::Service.instance).to receive(:start!) existing_team = Fabricate(:team, token: 'old', team_id: 'team_id', active: false) @@ -120,7 +131,7 @@ team = Team.find(team.id) expect(team.token).to eq 'token' expect(team.active).to be true - end.to_not change(Team, :count) + end.not_to change(Team, :count) end context 'with mailchimp settings' do @@ -130,8 +141,13 @@ config.mailchimp_list_id = 'list-id' end end + after do SlackRubyBotServer::Mailchimp.config.reset! + ENV.delete('MAILCHIMP_API_KEY') + ENV.delete('MAILCHIMP_LIST_ID') + ENV.delete('MAILCHIMP_API_KEY') + ENV.delete('MAILCHIMP_LIST_ID') end let(:list) { double(Mailchimp::List, members: double(Mailchimp::List::Members)) } @@ -170,10 +186,6 @@ client.teams._post(code: 'code') end - after do - ENV.delete('MAILCHIMP_API_KEY') - ENV.delete('MAILCHIMP_LIST_ID') - end end end end diff --git a/spec/api/swagger_documentation_spec.rb b/spec/api/swagger_documentation_spec.rb index a79b95f..acef112 100644 --- a/spec/api/swagger_documentation_spec.rb +++ b/spec/api/swagger_documentation_spec.rb @@ -8,6 +8,7 @@ get '/api/swagger_doc' JSON.parse(last_response.body) end + it 'documents root level apis' do expect(subject['paths'].keys.sort).to eq ['/api/status', '/api/teams/{id}', '/api/teams'].sort end @@ -18,6 +19,7 @@ get '/api/swagger_doc/teams' JSON.parse(last_response.body) end + it 'documents teams apis' do expect(subject['paths'].keys.sort).to eq ['/api/teams/{id}', '/api/teams'].sort end diff --git a/spec/initializers/shellwords_spec.rb b/spec/initializers/shellwords_spec.rb index 3a8d593..4338664 100644 --- a/spec/initializers/shellwords_spec.rb +++ b/spec/initializers/shellwords_spec.rb @@ -1,24 +1,27 @@ require 'spec_helper' describe Shellwords do - context '#parse' do + describe '#parse' do it 'splits a command line' do - command, pipe = Shellwords.parse('hello world') + command, pipe = described_class.parse('hello world') expect(command).to eq(%w(hello world)) - expect(pipe).to be nil + expect(pipe).to be_nil end + it 'splits a command line with pipe' do - command, pipe = Shellwords.parse('hello world|echo') + command, pipe = described_class.parse('hello world|echo') expect(command).to eq(%w(hello world)) expect(pipe).to eq('echo') end + it 'splits a command line with pipe punctuation' do - command, pipe = Shellwords.parse('hello world|$..foo') + command, pipe = described_class.parse('hello world|$..foo') expect(command).to eq(%w(hello world)) expect(pipe).to eq('$..foo') end + it 'splits a command line with pipe with spaces' do - command, pipe = Shellwords.parse('hello world | echo foo bar') + command, pipe = described_class.parse('hello world | echo foo bar') expect(command).to eq(%w(hello world)) expect(pipe).to eq('echo foo bar') end diff --git a/spec/integration/teams_spec.rb b/spec/integration/teams_spec.rb index 31cbfe9..2a392bd 100644 --- a/spec/integration/teams_spec.rb +++ b/spec/integration/teams_spec.rb @@ -1,14 +1,16 @@ require 'spec_helper' -describe 'Teams', js: true, type: :feature do +describe 'Teams', :js, type: :feature do before do ENV['SLACK_CLIENT_ID'] = 'client_id' ENV['SLACK_CLIENT_SECRET'] = 'client_secret' end + after do ENV.delete 'SLACK_CLIENT_ID' ENV.delete 'SLACK_CLIENT_SECRET' end + context 'oauth', vcr: { cassette_name: 'auth_test' } do it 'registers a team' do allow_any_instance_of(Team).to receive(:ping!).and_return(ok: true) @@ -17,17 +19,20 @@ allow_any_instance_of(Slack::Web::Client).to receive(:oauth_access).with(hash_including(code: 'code')).and_return(oauth_access) expect do visit '/?code=code' - expect(page.find('#messages')).to have_content 'Team successfully registered!' + expect(page.find_by_id('messages')).to have_content 'Team successfully registered!' end.to change(Team, :count).by(1) end end + context 'homepage' do before do visit '/' end + it 'displays index.html page' do expect(title).to eq('API Explorer for Slack') end + it 'includes a link to add to slack with the client id' do expect(find("a[href='https://slack.com/oauth/authorize?scope=bot&client_id=#{ENV['SLACK_CLIENT_ID']}']")) end diff --git a/spec/models/team_spec.rb b/spec/models/team_spec.rb index e6f4e35..3095c73 100644 --- a/spec/models/team_spec.rb +++ b/spec/models/team_spec.rb @@ -1,21 +1,22 @@ require 'spec_helper' describe Team do - context '#purge!' do + describe '#purge!' do let!(:active_team) { Fabricate(:team) } let!(:inactive_team) { Fabricate(:team, active: false) } let!(:inactive_team_a_week_ago) { Fabricate(:team, updated_at: 1.week.ago, active: false) } let!(:inactive_team_two_weeks_ago) { Fabricate(:team, updated_at: 2.weeks.ago, active: false) } let!(:inactive_team_a_month_ago) { Fabricate(:team, updated_at: 1.month.ago, active: false) } + it 'destroys teams inactive for two weeks' do expect do - Team.purge! - end.to change(Team, :count).by(-2) - expect(Team.find(active_team.id)).to eq active_team - expect(Team.find(inactive_team.id)).to eq inactive_team - expect(Team.find(inactive_team_a_week_ago.id)).to eq inactive_team_a_week_ago - expect(Team.find(inactive_team_two_weeks_ago.id)).to be nil - expect(Team.find(inactive_team_a_month_ago.id)).to be nil + described_class.purge! + end.to change(described_class, :count).by(-2) + expect(described_class.find(active_team.id)).to eq active_team + expect(described_class.find(inactive_team.id)).to eq inactive_team + expect(described_class.find(inactive_team_a_week_ago.id)).to eq inactive_team_a_week_ago + expect(described_class.find(inactive_team_two_weeks_ago.id)).to be_nil + expect(described_class.find(inactive_team_a_month_ago.id)).to be_nil end end end diff --git a/spec/slack-api-explorer/commands/default_spec.rb b/spec/slack-api-explorer/commands/default_spec.rb index 8188b88..13d7ed7 100644 --- a/spec/slack-api-explorer/commands/default_spec.rb +++ b/spec/slack-api-explorer/commands/default_spec.rb @@ -5,11 +5,13 @@ let(:app) { SlackApiExplorer::Server.new(team: team) } let(:client) { app.send(:client) } let(:message_hook) { SlackRubyBot::Hooks::Message.new } + it 'default' do expect(client).to receive(:say).with(channel: 'channel', text: SlackApiExplorer::INFO) expect(client).to receive(:say).with(channel: 'channel', gif: 'robot') message_hook.call(client, Hashie::Mash.new(channel: 'channel', text: SlackRubyBot.config.user)) end + it 'upcase' do expect(client).to receive(:say).with(channel: 'channel', text: SlackApiExplorer::INFO) expect(client).to receive(:say).with(channel: 'channel', gif: 'robot') diff --git a/spec/slack-api-explorer/commands/slack_spec.rb b/spec/slack-api-explorer/commands/slack_spec.rb index 96265b6..7c95621 100644 --- a/spec/slack-api-explorer/commands/slack_spec.rb +++ b/spec/slack-api-explorer/commands/slack_spec.rb @@ -5,9 +5,11 @@ let(:app) { SlackApiExplorer::Server.new(team: team) } let(:client) { app.send(:client) } let(:message_hook) { SlackRubyBot::Hooks::Message.new } + it 'auth' do expect(message: "#{SlackRubyBot.config.user} auth").to respond_with_slack_message("```\nerror: Command 'auth' requires a subcommand revoke,test```") end + context 'auth test' do let(:json) do { @@ -19,19 +21,24 @@ user_id: 'U07518DTL' } end + before do - allow(SlackApiExplorer::Commands::Slack).to receive(:execute).and_yield(JSON.dump(json), nil) + allow(described_class).to receive(:execute).and_yield(JSON.dump(json), nil) end + it 'returns raw json' do expect(message: "#{SlackRubyBot.config.user} auth test").to respond_with_slack_message("```\n#{JSON.pretty_generate(json)}```") end + it 'processes a json value' do expect(message: "#{SlackRubyBot.config.user} auth test | $.team_id").to respond_with_slack_message("```\n[\n \"T04KB5WQH\"\n]```") end + it 'responds to a slack ID' do expect(message: "<@#{SlackRubyBot.config.user_id}>: auth test").to respond_with_slack_message("```\n#{JSON.pretty_generate(json)}```") end end + context 'channels list' do let(:json) do { @@ -64,24 +71,30 @@ ] } end + before do - allow(SlackApiExplorer::Commands::Slack).to receive(:execute).and_yield(JSON.dump(json), nil) + allow(described_class).to receive(:execute).and_yield(JSON.dump(json), nil) end + it 'returns multiple json values' do expect(message: "#{SlackRubyBot.config.user} channels list | $..name").to respond_with_slack_message("```\n[\n \"general\",\n \"random\"\n]```") end + it 'returns general channel' do output = JSON.pretty_generate([json[:channels][0]]) expect(message: "#{SlackRubyBot.config.user} channels list | $..[?(@.name=='general')]").to respond_with_slack_message("```\n#{output}```") end + it 'returns id of the general channel' do expect(message: "#{SlackRubyBot.config.user} channels list | $..[?(@.name=='general')].id").to respond_with_slack_message("```\n[\n \"C09C5GYHF\"\n]```") end end + context 'chat postMessage' do it 'unescapes channel' do - expect(SlackApiExplorer::Commands::Slack).to receive(:execute).with(client, - ['chat', 'postMessage', '--text', 'Hello World', '--channel', '#C04KB5X4D']).and_yield(JSON.dump(ok: true), nil) + expect(described_class).to receive(:execute).with(client, + ['chat', 'postMessage', '--text', + 'Hello World', '--channel', '#C04KB5X4D']).and_yield(JSON.dump(ok: true), nil) expect(message: "#{SlackRubyBot.config.user} chat postMessage --text 'Hello World' --channel <#C04KB5X4D>").to respond_with_slack_message("```\n{\n \"ok\": true\n}```") end end diff --git a/spec/slack-api-explorer/commands/unknown_spec.rb b/spec/slack-api-explorer/commands/unknown_spec.rb index 4fa4698..b1d5093 100644 --- a/spec/slack-api-explorer/commands/unknown_spec.rb +++ b/spec/slack-api-explorer/commands/unknown_spec.rb @@ -5,11 +5,13 @@ let(:app) { SlackApiExplorer::Server.new(team: team) } let(:client) { app.send(:client) } let(:message_hook) { SlackRubyBot::Hooks::Message.new } + it 'invalid command' do expect(message: "#{SlackRubyBot.config.user} foobar").to respond_with_slack_message("```\nerror: Unknown command 'foobar'```") end + it 'does not respond to sad face' do - expect(SlackRubyBot::Commands::Base).to_not receive(:send_message) + expect(SlackRubyBot::Commands::Base).not_to receive(:send_message) message_hook.call(client, Hashie::Mash.new(text: ':((')) end end diff --git a/spec/slack-api-explorer/version_spec.rb b/spec/slack-api-explorer/version_spec.rb index da85e6f..2f41bfc 100644 --- a/spec/slack-api-explorer/version_spec.rb +++ b/spec/slack-api-explorer/version_spec.rb @@ -2,6 +2,6 @@ describe SlackApiExplorer do it 'has a version' do - expect(SlackApiExplorer::VERSION).to_not be nil + expect(SlackApiExplorer::VERSION).not_to be_nil end end diff --git a/spec/support/api/endpoints/endpoint_test.rb b/spec/support/api/endpoints/endpoint_test.rb index e549436..06f34ea 100644 --- a/spec/support/api/endpoints/endpoint_test.rb +++ b/spec/support/api/endpoints/endpoint_test.rb @@ -15,8 +15,8 @@ module EndpointTest conn.request :json conn.response :json conn.use Faraday::Response::RaiseError - conn.use FaradayMiddleware::FollowRedirects - conn.use Faraday::Adapter::Rack, app + conn.use Faraday::FollowRedirects::Middleware + conn.adapter Faraday::Adapter::Rack, app end end end diff --git a/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb b/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb index be87512..5bc14ad 100644 --- a/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb +++ b/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb @@ -8,19 +8,15 @@ 12.times { Fabricate(model_s) } end - it 'returns 10 items by default' do - expect(client.send(model_ps, cursor_params).count).to eq 10 - end - - it 'returns 2 items' do - expect(client.send(model_ps, cursor_params.merge(size: 2)).count).to eq 2 + it 'returns all items by default' do + expect(client.send(model_ps, cursor_params).count).to eq 12 end it 'returns a first page with a cursor' do response = client.send(model_ps, cursor_params.merge(size: 2)) expect(response._links.self._url).to eq "http://example.org/api/#{model_ps}?#{cursor_params.merge(size: 2).to_query}" expect(response._links.next._url).to start_with "http://example.org/api/#{model_ps}?" - expect(response._links.next._url).to match(/cursor\=.*%3A\h*/) + expect(response._links.next._url).to match(/cursor=.*%3A\h*/) end it 'paginates over the entire collection' do @@ -31,7 +27,7 @@ models_ids.concat(response.map { |instance| instance._links.self._url.gsub("http://example.org/api/#{model_ps}/", '') }) break unless response._links[:next] - next_cursor = Hash[CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }] + next_cursor = CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }.to_h end expect(models_ids.uniq.count).to eq model.all.count end @@ -44,7 +40,7 @@ models_ids.concat(response.map { |instance| instance._links.self._url.gsub("http://example.org/api/#{model_ps}/", '') }) break unless response._links[:next] - next_cursor = Hash[CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }] + next_cursor = CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }.to_h end expect(models_ids.uniq.count).to eq model.all.count - 3 end @@ -52,8 +48,9 @@ context 'total count' do it "doesn't return total_count" do response = client.send(model_ps, cursor_params) - expect(response).to_not respond_to(:total_count) + expect(response).not_to respond_to(:total_count) end + it 'returns total_count when total_count query string is specified' do response = client.send(model_ps, cursor_params.merge(total_count: true)) expect(response.total_count).to eq model.all.count @@ -62,7 +59,7 @@ it 'returns all unique ids' do instances = client.send(model_ps, cursor_params) - expect(instances.map(&:id).uniq.count).to eq 10 + expect(instances.map(&:id).uniq.count).to eq 12 end end end diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb index 348130b..4ccef29 100644 --- a/spec/support/database_cleaner.rb +++ b/spec/support/database_cleaner.rb @@ -1,16 +1,16 @@ -require 'database_cleaner' +require 'database_cleaner-mongoid' RSpec.configure do |config| config.before :suite do - DatabaseCleaner.strategy = :truncation - DatabaseCleaner.clean_with :truncation + DatabaseCleaner.strategy = :deletion + DatabaseCleaner.clean_with :deletion end config.after :suite do Mongoid.purge! end - config.around :each do |example| + config.around do |example| DatabaseCleaner.cleaning do example.run end