-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VCR use_cassette middleware #167
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThe changes in this pull request enhance the Cypress on Rails framework by introducing new configuration options for VCR middleware, specifically through the Changes
Possibly related issues
Tip CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
cypress-on-rails Run #133
Run Properties:
|
Project |
cypress-on-rails
|
Branch Review |
new-vcr-middleware
|
Run status |
Passed #133
|
Run duration | 00m 10s |
Commit |
1bc82b6ae6 ℹ️: Merge 5afef6afa8a6885d81701fcdc3dcd1334796cc81 into dcea71969846e26d05e073a56f3c...
|
Committer | Anton |
View all properties for this run ↗︎ |
Test results | |
---|---|
Failures |
0
|
Flaky |
0
|
Pending |
0
|
Skipped |
0
|
Passing |
10
|
View all changes introduced in this branch ↗︎ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Outside diff range and nitpick comments (3)
lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb (1)
9-11
: Consider enabling the new VCR middleware configuration.The new configuration options for VCR middleware are commented out. Ensure to enable them as needed and provide appropriate documentation.
- # c.use_vcr_use_cassette_middleware = !Rails.env.production? - # c.vcr_use_cassette_mode = :once # Use to choose VCR record mode (:new_episodes by default) + c.use_vcr_use_cassette_middleware = !Rails.env.production? + c.vcr_use_cassette_mode = :once # Use to choose VCR record mode (:new_episodes by default)lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js (1)
26-47
: Consider enabling the new GraphQL commands.The new commands for GraphQL usage are commented out. Ensure to enable them as needed and provide appropriate documentation.
- // Cypress.Commands.add('mockGraphQL', () => { - // cy.on('window:before:load', (win) => { - // const originalFetch = win.fetch; - // const fetch = (path, options, ...rest) => { - // if (options && options.body) { - // try { - // const body = JSON.parse(options.body); - // if (body.operationName) { - // return originalFetch(`${path}?operation=${body.operationName}`, options, ...rest); - // } - // } catch (e) { - // return originalFetch(path, options, ...rest); - // } - // } - // return originalFetch(path, options, ...rest); - // }; - // cy.stub(win, 'fetch', fetch); - // }); - // }); + Cypress.Commands.add('mockGraphQL', () => { + cy.on('window:before:load', (win) => { + const originalFetch = win.fetch; + const fetch = (path, options, ...rest) => { + if (options && options.body) { + try { + const body = JSON.parse(options.body); + if (body.operationName) { + return originalFetch(`${path}?operation=${body.operationName}`, options, ...rest); + } + } catch (e) { + return originalFetch(path, options, ...rest); + } + } + return originalFetch(path, options, ...rest); + }; + cy.stub(win, 'fetch', fetch); + }); + });lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js (1)
50-50
: Consider enabling the new GraphQL commands.The new commands for GraphQL usage are commented out. Ensure to enable them as needed and provide appropriate documentation.
- // cy.mockGraphQL(); // for GraphQL usage, see cypress/support/commands.rb + cy.mockGraphQL(); // for GraphQL usage, see cypress/support/commands.rb
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (11)
- lib/cypress_on_rails/configuration.rb (2 hunks)
- lib/cypress_on_rails/railtie.rb (1 hunks)
- lib/cypress_on_rails/vcr/base_middleware.rb (1 hunks)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1 hunks)
- lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1 hunks)
- lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb (1 hunks)
- lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js (1 hunks)
- lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js (1 hunks)
- spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (1 hunks)
- spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb (1 hunks)
- specs_e2e/rails_3_2/config/boot.rb (1 hunks)
Files skipped from review due to trivial changes (1)
- specs_e2e/rails_3_2/config/boot.rb
Additional comments not posted (28)
lib/cypress_on_rails/railtie.rb (2)
12-14
: Ensure Vcr::InsertEjectMiddleware is correctly integrated.The middleware
Vcr::InsertEjectMiddleware
is integrated based on theuse_vcr_middleware?
configuration setting.Ensure the
Vcr::InsertEjectMiddleware
is correctly implemented and tested.
15-17
: Ensure Vcr::UseCassetteMiddleware is correctly integrated.The middleware
Vcr::UseCassetteMiddleware
is integrated based on theuse_vcr_use_cassette_middleware?
configuration setting.Ensure the
Vcr::UseCassetteMiddleware
is correctly implemented and tested.lib/cypress_on_rails/vcr/base_middleware.rb (5)
11-13
: Abstract methodinitialize
should not be called directly.The
initialize
method raises aNotImplementedError
to prevent direct instantiation ofBaseMiddleware
.
15-17
: Abstract methodcall
should not be called directly.The
call
method raises aNotImplementedError
to prevent direct invocation onBaseMiddleware
.
19-21
: Lazy initialization of VCR configuration.The
vcr
method lazily initializes the VCR configuration by callingconfigure_vcr
.
25-31
: VCR configuration method.The
configure_vcr
method sets up the VCR configuration, including the cassette library directory.
33-36
: Raise error for direct instantiation.The
raise_not_implemented
method raises an error to indicate thatBaseMiddleware
should not be instantiated directly.lib/cypress_on_rails/vcr/use_cassette_middleware.rb (5)
8-11
: Ensure correct initialization of UseCassetteMiddleware.The
initialize
method sets up the middleware with the provided app and VCR instance.
13-20
: Handle VCR interactions with use_cassette.The
call
method handles VCR interactions using theuse_cassette
method based on the request path.
24-26
: Access configuration settings.The
configuration
method returns the CypressOnRails configuration.
28-30
: Access logger instance.The
logger
method returns the logger instance from the configuration.
32-38
: Fetch cassette name based on request path.The
fetch_request_cassette
method determines the cassette name based on the request path and parameters.lib/cypress_on_rails/configuration.rb (5)
9-9
: New configuration optionuse_vcr_use_cassette_middleware
.The
use_vcr_use_cassette_middleware
option controls the use of VCR middleware.
12-12
: New configuration optionvcr_use_cassette_mode
.The
vcr_use_cassette_mode
option sets the VCR cassette recording mode.
30-30
: Alias foruse_vcr_use_cassette_middleware
.The alias
use_vcr_use_cassette_middleware?
allows querying the configuration option.
37-37
: Reset configuration optionuse_vcr_use_cassette_middleware
.The
reset
method sets the default value foruse_vcr_use_cassette_middleware
tofalse
.
40-40
: Reset configuration optionvcr_use_cassette_mode
.The
reset
method sets the default value forvcr_use_cassette_mode
to:new_episodes
.spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb (1)
1-44
: LGTM!The new test cases for
UseCassetteMiddleware
are correctly implemented and cover necessary scenarios.lib/cypress_on_rails/vcr/insert_eject_middleware.rb (4)
7-11
: LGTM!The
initialize
method correctly sets up the middleware with the application and VCR instance.
39-41
: LGTM!The
parse_request_body
method correctly parses the request body as JSON.
53-60
: LGTM!The
handle_eject
method correctly manages the ejection of VCR cassettes and handles errors.
62-68
: LGTM!The
do_first_call
method correctly handles the first call setup for VCR and WebMock.spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (6)
20-35
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/insert
path.
37-46
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/insert
path with therecord
option.
48-57
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/insert
path with thematch_requests_on
option.
59-68
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/insert
path with theserialize_with
option.
70-79
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/insert
path with thepersist_with
option.
82-96
: LGTM!The test case correctly verifies the middleware's behavior for the
/__e2e__/vcr/eject
path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb
end | ||
|
||
def call(env) | ||
return @app.call(env) if should_not_use_vcr? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a workaround to skip behavior if VCR is already in use (rspec, for example)
@MUTOgen any word on getting this merged? |
@justin808 Yep, it should be ready for review now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Outside diff range and nitpick comments (3)
README.md (1)
358-360
: Looks good! Just a minor formatting suggestion.The added content clearly explains the two modes of using VCR.
For consistency, consider using the same unordered list style (asterisk or dash) for both list items:
- - with separate insert/eject calls (more general, recommended way) - - with use_cassette wrapper (supports only GraphQL integration) + * with separate insert/eject calls (more general, recommended way) + * with use_cassette wrapper (supports only GraphQL integration)Tools
Markdownlint
359-359: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
360-360: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
lib/cypress_on_rails/vcr/base_middleware.rb (2)
26-26
: Consider requiring 'vcr' at the top of the file for clarityRequiring
'vcr'
within theconfigure_vcr
method delays the loading of thevcr
gem until this method is called. For clarity and to ensure that missing dependencies are caught early, it's advisable to require all dependencies at the top of the file.Apply this diff to move the require statement:
+require 'vcr' module CypressOnRails module Vcr # Base abstract Middleware class BaseMiddleware include MiddlewareConfig # ... existing methods ... private - def configure_vcr - require 'vcr' + def configure_vcr VCR.configure do |config| config.cassette_library_dir = cassette_library_dir end VCR end
39-39
: Typographical correction in error messageIn the error message, "can not" should be "cannot" to adhere to standard spelling conventions.
Apply this diff to correct the typo:
def raise_not_implemented raise NotImplementedError, - 'BaseMiddleware can not be initialized directly, use InsertEjectMiddleware or UseCassetteMiddleware' + 'BaseMiddleware cannot be initialized directly, use InsertEjectMiddleware or UseCassetteMiddleware' end
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (9)
- README.md (3 hunks)
- lib/cypress_on_rails/configuration.rb (2 hunks)
- lib/cypress_on_rails/railtie.rb (1 hunks)
- lib/cypress_on_rails/vcr/base_middleware.rb (1 hunks)
- lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1 hunks)
- lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb (1 hunks)
- lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js (1 hunks)
- spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb (1 hunks)
- specs_e2e/rails_4_2/Gemfile (1 hunks)
Files skipped from review due to trivial changes (1)
- lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js
Additional context used
Markdownlint
README.md
359-359: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
360-360: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
rubocop
lib/cypress_on_rails/vcr/use_cassette_middleware.rb
[warning] 7-10: Call
super
to initialize state of the parent class.(Lint/MissingSuper)
Additional comments not posted (20)
specs_e2e/rails_4_2/Gemfile (1)
6-8
: LGTM! The change is well-documented and addresses a specific issue.The addition of the
bigdecimal
gem with a specific version constraint is a good solution to address theNoMethodError
issue related to theBigDecimal
class. The comments provide a clear explanation of the purpose of the change and include a reference to a GitHub page for further guidance on selecting the appropriate version.This change demonstrates good practices by:
- Specifying a specific version constraint to ensure compatibility.
- Providing clear comments explaining the purpose of the change.
- Including a reference to a relevant resource for additional information.
lib/cypress_on_rails/railtie.rb (3)
12-13
: LGTM! The new middleware enhances VCR functionality.The
Vcr::InsertEjectMiddleware
replaces the previousVCRMiddleware
. This new middleware likely handles the insertion and ejection of VCR cassettes, providing more granular control over VCR usage in the testing environment.The change is conditional based on the
use_vcr_middleware?
configuration option, allowing flexibility in enabling or disabling this functionality.
15-17
: Great addition! The new middleware enhances VCR cassette usage.The introduction of the
Vcr::UseCassetteMiddleware
middleware, conditionally enabled by the newuse_vcr_use_cassette_middleware?
configuration option, adds a new layer of functionality for using VCR cassettes during tests.This middleware likely handles the usage of VCR cassettes, providing more control and flexibility over how external requests are handled in the testing environment.
The conditional nature of this middleware allows users to enable or disable this functionality based on their specific testing needs.
Line range hint
1-23
: Overall, the changes in this file are excellent! They enhance VCR functionality and provide more control over its usage.The introduction of the
Vcr::InsertEjectMiddleware
andVcr::UseCassetteMiddleware
middleware classes, along with their corresponding configuration options, allows for more granular control over VCR usage in the testing environment.These changes provide flexibility in enabling or disabling specific VCR functionalities based on the user's testing needs. The conditional nature of the middleware additions ensures that the functionality is only included when desired.
The code changes are well-structured, follow the existing code patterns, and integrate seamlessly with the existing codebase.
Great work on enhancing the VCR capabilities of the
cypress_on_rails
package!lib/cypress_on_rails/configuration.rb (4)
9-9
: LGTM!The new attribute
use_vcr_use_cassette_middleware
is declared correctly usingattr_accessor
. The naming clearly conveys its purpose as a flag to control the usage of VCR'suse_cassette
middleware.
12-12
: LGTM!The new attribute
vcr_record_mode
is declared correctly usingattr_accessor
. The naming clearly conveys its purpose as a configuration for setting the record mode for VCR.
30-30
: LGTM!The alias method
use_vcr_use_cassette_middleware?
is defined correctly for the attributeuse_vcr_use_cassette_middleware
. The naming convention of appending?
is consistent with Ruby's conventions for predicate methods, making the code more readable.
37-37
: LGTM!The
reset
method is updated correctly to initialize the new attributesuse_vcr_use_cassette_middleware
andvcr_record_mode
with appropriate default values:
use_vcr_use_cassette_middleware
is set tofalse
, disabling the usage of VCR'suse_cassette
middleware by default.vcr_record_mode
is set to:new_episodes
, configuring VCR to record new interactions while replaying existing ones by default.The changes ensure that the new attributes have consistent default values when the configuration is reset.
Also applies to: 40-40
lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb (1)
9-11
: LGTM! The new configuration options provide flexibility for VCR middleware.The added configuration options,
use_vcr_use_cassette_middleware
andvcr_record_mode
, allow users to customize the behavior of VCR middleware in their Cypress tests.
use_vcr_use_cassette_middleware
, when enabled, allows the use of theuse_cassette
wrapper, which can simplify the usage of VCR in tests by automatically handling the cassette lifecycle.vcr_record_mode
allows setting the VCR record mode, which determines how VCR records and replays HTTP interactions during tests. For example, setting it to:once
would record interactions once and replay them in subsequent test runs.By keeping these options commented out by default, the changes maintain backward compatibility and allow users to opt-in to the new functionality as needed.
spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb (4)
24-31
: LGTM!The test case correctly verifies the middleware's behavior when handling a GraphQL request. It ensures that the middleware returns the application response and invokes VCR with the appropriate cassette path and recording mode.
33-41
: LGTM!The test case correctly verifies the middleware's behavior when using the default request path cassette. It ensures that the middleware returns the application response and invokes VCR with the appropriate cassette path and recording mode based on the configuration.
43-54
: LGTM!The test case correctly verifies the middleware's behavior when the VCR cassette library directory does not match. It ensures that the middleware returns the application response without invoking VCR, as expected in this scenario.
56-69
: Skip this test case.The test case seems to have an inconsistency. It sets up the environment with VCR not defined, but still expects VCR to have received the
use_cassette
method. If VCR is not defined, the middleware should not invoke VCR at all. Please review and update the test case accordingly.README.md (4)
387-393
: LGTM!The setup instructions for insert/eject mode are clear and the commented out configuration for use_cassette mode is a helpful reference.
423-436
: Looks good!The setup instructions for use_cassette mode are comprehensive and cover the necessary configuration steps.
438-461
: Great addition!The custom
mockGraphQL
command is a smart way to enable VCR to capture GraphQL requests by operation name. The code is well-structured and includes proper error handling.
463-475
: Looks good!The usage instructions clearly explain that no special calls are needed in Cypress scenarios when using VCR with use_cassette mode. It's helpful to mention that cassettes will be automatically recorded and saved.
lib/cypress_on_rails/vcr/base_middleware.rb (2)
11-17
: Ensure subclasses properly implement 'initialize' and 'call' methodsSince
BaseMiddleware
is an abstract class withinitialize
andcall
methods raisingNotImplementedError
, ensure that all subclasses override these methods with concrete implementations to provide the intended functionality.Run the following script to confirm that subclasses implement the required methods:
#!/bin/bash # Description: Verify subclasses of BaseMiddleware implement 'initialize' and 'call' methods. # Find all subclasses of BaseMiddleware rg --type ruby 'class (\w+) < BaseMiddleware' -o -r '$1' | while read -r subclass; do echo "Checking $subclass..." # Check for 'def initialize' in subclass rg --type ruby -A 5 "class ${subclass} < BaseMiddleware" | rg 'def initialize' >/dev/null || echo "Warning: ${subclass} may not implement 'initialize'" # Check for 'def call' in subclass rg --type ruby -A 5 "class ${subclass} < BaseMiddleware" | rg 'def call' >/dev/null || echo "Warning: ${subclass} may not implement 'call'" done
34-34
: Verify that 'configuration' is accessible within the methodEnsure that the
configuration
method is defined and accessible within the context ofcassette_library_dir
. Sinceconfiguration
is expected to be provided byMiddlewareConfig
, verify that it is correctly included and initialized.Run the following script to check for the definition of
configuration
:Verification successful
'configuration' method is accessible in BaseMiddleware
The verification process confirms that the 'configuration' method is indeed accessible within the context of the 'cassette_library_dir' method in BaseMiddleware. Here's why:
- BaseMiddleware includes the MiddlewareConfig module.
- MiddlewareConfig defines the 'configuration' method, which returns CypressOnRails.configuration.
- By including MiddlewareConfig, BaseMiddleware and its subclasses gain access to the 'configuration' method.
Therefore, the use of 'configuration.install_folder' in the code snippet is valid and should work as expected.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that 'configuration' method is defined in MiddlewareConfig. # Test: Search for 'def configuration' within MiddlewareConfig module. Expect: Method definition exists. rg --type ruby -A 5 -B 2 'module MiddlewareConfig' | rg 'def configuration'Length of output: 1031
Script:
#!/bin/bash # 1. Check BaseMiddleware class definition and MiddlewareConfig inclusion echo "Checking BaseMiddleware class definition:" rg --type ruby -A 5 "class BaseMiddleware" echo "\nChecking if BaseMiddleware includes MiddlewareConfig:" rg --type ruby "class BaseMiddleware" -A 10 | rg "include MiddlewareConfig" # 2. Look for 'configuration' in MiddlewareConfig echo "\nSearching for 'configuration' in MiddlewareConfig:" rg --type ruby -A 5 "module MiddlewareConfig" | rg -A 5 "def configuration" # 3. Examine BaseMiddleware for 'configuration' usage echo "\nExamining BaseMiddleware for 'configuration' usage:" rg --type ruby "class BaseMiddleware" -A 20 | rg "configuration" # 4. Check for initializer in BaseMiddleware echo "\nChecking for initializer in BaseMiddleware:" rg --type ruby "class BaseMiddleware" -A 20 | rg "def initialize"Length of output: 1623
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1)
13-13
: Existing handling of VCR usage conditionAs previously noted, the early return in
call
method serves as a workaround to skip behavior if VCR is already in use (e.g., with RSpec). This implementation is acceptable given the context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (3)
lib/cypress_on_rails/vcr/middleware_helpers.rb (3)
9-12
: LGTM: Well-structured initialize method with a minor suggestion.The initialize method is well-designed, allowing for dependency injection of both the app and vcr instances. The default value of nil for vcr enables lazy initialization.
Consider adding a brief comment explaining the purpose of the
app
andvcr
parameters for improved clarity:# @param app [Object] The Rack application # @param vcr [VCR, nil] Optional VCR instance for testing def initialize(app, vcr = nil) @app = app @vcr = vcr end
14-20
: LGTM: Well-implemented vcr and cassette_library_dir methods with a suggestion for improvement.The vcr method's lazy initialization is a good practice for performance. The cassette_library_dir method appropriately uses the configuration's install_folder to define the path for storing VCR cassettes.
Consider adding error handling to the
cassette_library_dir
method to ensure the install_folder is set:def cassette_library_dir raise "Configuration install_folder is not set" if configuration.install_folder.nil? "#{configuration.install_folder}/fixtures/vcr_cassettes" endThis will provide a more informative error message if the configuration is not properly set.
22-31
: LGTM: Well-implemented configure_vcr method with suggestions for improvement.The
configure_vcr
method is well-structured, with lazy loading of the VCR library and appropriate configuration of the cassette library directory.Consider the following improvements:
- Add error handling for VCR library loading:
def configure_vcr begin require 'vcr' rescue LoadError raise "VCR library is not available. Please ensure it's properly installed." end # ... rest of the method end
- Allow for more flexible VCR configuration:
def configure_vcr require 'vcr' VCR.configure do |config| config.cassette_library_dir = cassette_library_dir # Add more default configuration options here yield(config) if block_given? end VCR endThis change allows users to pass a block with additional configuration options if needed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1 hunks)
- lib/cypress_on_rails/vcr/middleware_helpers.rb (1 hunks)
- lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1 hunks)
🔇 Additional comments (3)
lib/cypress_on_rails/vcr/middleware_helpers.rb (1)
1-8
: LGTM: Appropriate module structure and configuration inclusion.The module is correctly defined within the
CypressOnRails::Vcr
namespace, and the inclusion ofMiddlewareConfig
is appropriate for accessing configuration-related methods.lib/cypress_on_rails/vcr/insert_eject_middleware.rb (2)
21-22
: Fix potential race conditionThe previous comment regarding a potential race condition is still applicable. Setting
@first_call
after callingdo_first_call
could lead to unintended behavior in a multi-threaded environment.
44-52
: Add validation for request bodyThe earlier suggestion to validate the request body is still valid. Ensuring that
body
is an array with at least one element will prevent potential errors when accessingbody[0]
andbody[1]
.
rescue LoadError, ArgumentError => e | ||
[501, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use appropriate HTTP status code for server errors
In the rescue clauses of handle_insert
and handle_eject
, 501 Not Implemented
is used to indicate errors caused by LoadError
or ArgumentError
. The 501
status code implies that the server does not support the functionality required to fulfill the request, which may not accurately represent these error cases. Consider using 500 Internal Server Error
to represent unexpected server errors more appropriately.
Apply this diff to correct the status code:
-rescue LoadError, ArgumentError => e
- [501, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]]
+rescue LoadError, ArgumentError => e
+ [500, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]]
Also applies to: 59-61
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree 👍🏽
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@grantspeelman Glad you agree!
(^・ω・^)
@MUTOgen any updates? @grantspeelman can you give us your thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all looks good to me.
Be interesting to see if this is viable in practice 👍🏽
rescue LoadError, ArgumentError => e | ||
[501, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree 👍🏽
rescue LoadError, ArgumentError => e | ||
[501, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rescue LoadError, ArgumentError => e | |
[501, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]] | |
rescue LoadError, ArgumentError => e | |
[500, { 'Content-Type' => 'application/json' }, [{ 'message': e.message }.to_json]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (2)
lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1)
63-69
: Log exceptions instead of suppressing themIn the
do_first_call
method, rescuingLoadError
without any action (# nop
) can make debugging difficult if an error occurs. Consider logging the exception to aid in troubleshooting.Apply this diff to log the exception:
rescue LoadError => e - # nop + logger.error "LoadError in do_first_call: #{e.message}"spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (1)
31-31
: Add Trailing Commas to Multiline Arrays for ConsistencyAdding a trailing comma after the last item of a multiline array enhances code consistency and makes future diffs cleaner.
Apply the following changes:
At line 31:
expect(response).to eq([201, { 'Content-Type' => 'application/json' }, - ['{"message":"OK"}']]) + ['{"message":"OK"}',]])Similarly, add trailing commas at the end of multiline arrays at lines 43, 54, 65, 76, 89, 100, 115, 128, and 138.
[Style/TrailingCommaInArrayLiteral]
Also applies to: 43-43, 54-54, 65-65, 76-76, 89-89, 100-100, 115-115, 128-128, 138-138
🧰 Tools
🪛 rubocop
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1 hunks)
- spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (1 hunks)
🧰 Additional context used
🪛 rubocop
spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb
[convention] 6-166: Module has too many lines. [130/100]
(Metrics/ModuleLength)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 115-115: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 128-128: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
🔇 Additional comments (2)
lib/cypress_on_rails/vcr/insert_eject_middleware.rb (2)
21-22
: Potential race condition when setting@first_call
As previously noted, setting
@first_call
after callingdo_first_call
may lead to race conditions in multi-threaded environments. It's safer to set@first_call = true
before callingdo_first_call
to prevent concurrent threads from executingdo_first_call
multiple times.Apply this diff to fix the potential race condition:
-def call(env) - request = Rack::Request.new(env) - if request.path.start_with?('/__e2e__/vcr/insert') - configuration.tagged_logged { handle_insert(request) } - elsif request.path.start_with?('/__e2e__/vcr/eject') - configuration.tagged_logged { handle_eject } - else - do_first_call unless @first_call + unless @first_call + @first_call = true + do_first_call + end @app.call(env) end end
44-52
: Validate cassette information inextract_cassette_info
As previously noted, there is no validation to ensure that
body
is an array with at least one element. Accessingbody[0]
without validation might raise an exception ifbody
isnil
or not in the expected format. Ensure thatbody
is properly validated before extracting cassette information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (3)
spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (2)
154-174
: Minor improvement suggestion for "Other paths" tests.The "Other paths" tests look good and cover the necessary scenarios. However, in the second test (lines 162-173), you're using
aggregate_failures
but not taking full advantage of it. Consider moving the expectations inside the loop to truly aggregate failures for each path. This would provide more detailed information if a test fails.Here's a suggested improvement:
it 'runs app for various paths' do %w[/ /__e2e__/login command /e2e_command /].each do |path| env['PATH_INFO'] = path response = subject.call(env) aggregate_failures do expect(response).to eq([200, {}, ["app did #{path}"]]) expect(vcr).to have_received(:turn_off!) end end endThis change would report failures for each path separately, making it easier to identify which specific path(s) caused a test failure.
1-177
: Address RuboCop style issues.RuboCop has flagged a few style issues in this file:
The module exceeds the recommended maximum line count (138 lines vs. 100 lines limit). Given the comprehensive nature of these tests, this may be acceptable. However, consider if any further refactoring (such as the shared examples suggested earlier) could help reduce the overall line count.
There are multiple instances of missing trailing commas in multiline arrays. To improve consistency and make future additions easier, consider adding trailing commas to all multiline arrays in the file. For example:
expect(response).to eq([201, { 'Content-Type' => 'application/json' }, ['{"message":"OK"}'],])Addressing these style issues will improve the overall code quality and maintainability.
🧰 Tools
🪛 rubocop
[convention] 6-176: Module has too many lines. [138/100]
(Metrics/ModuleLength)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 111-111: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 125-125: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 148-148: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1)
47-53
: Consider sanitizing cassette names to ensure valid file paths.In the
fetch_request_cassette
method, cassette names may include forward slashes (e.g.,'/graphql/operationName'
). This could lead to issues when VCR tries to save or retrieve cassette files, as some file systems may not handle slashes in file names as intended. Consider replacing slashes and other potentially problematic characters with safe alternatives.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb (1 hunks)
- lib/cypress_on_rails/vcr/middleware_helpers.rb (1 hunks)
- lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1 hunks)
- spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb
🧰 Additional context used
🪛 rubocop
spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb
[convention] 6-176: Module has too many lines. [138/100]
(Metrics/ModuleLength)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 111-111: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 125-125: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 148-148: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
🔇 Additional comments (5)
lib/cypress_on_rails/vcr/middleware_helpers.rb (2)
1-8
: LGTM: Module structure and dependencies are well-organized.The module is correctly namespaced within
CypressOnRails::Vcr
, and the inclusion ofMiddlewareConfig
suggests proper use of configuration options. The structure is clean and follows Ruby conventions.
9-11
: LGTM: Efficient VCR configuration with memoization.The
vcr
method uses memoization to ensure that VCR is configured only once, which is an excellent practice for performance optimization. The use of a private method for configuration keeps the public interface clean and follows the principle of encapsulation.spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (3)
1-6
: LGTM: File structure and imports are appropriate.The file structure and imports are well-organized and include all necessary dependencies for the tests. The nested module structure (CypressOnRails::Vcr) is appropriate for the context of this spec file.
7-19
: LGTM: Test setup is comprehensive and well-structured.The test setup provides all necessary mocks and helpers for the tests. The use of
let
statements forapp
,vcr
, andenv
allows for easy reuse and modification in individual test cases. Therack_input
helper method is a nice touch for simplifying JSON input creation.
1-177
: Overall assessment: Well-structured and comprehensive tests with room for minor improvements.This spec file for InsertEjectMiddleware is well-written and covers a wide range of scenarios for VCR cassette insertion and ejection. The tests are thorough and provide good coverage of both successful operations and error handling.
Key strengths:
- Comprehensive test coverage for different VCR options and error cases.
- Well-structured setup with appropriate use of RSpec features like
let
andbefore
.- Clear separation of concerns between insert, eject, and other path tests.
Suggestions for improvement:
- Refactor repetitive test structures using shared examples or custom matchers.
- Minor adjustments to the "Other paths" tests for better failure reporting.
- Address style issues flagged by RuboCop, particularly trailing commas in multiline arrays.
These improvements would enhance the maintainability and readability of the tests without compromising their effectiveness. Overall, this is a solid test suite that provides confidence in the functionality of the InsertEjectMiddleware.
🧰 Tools
🪛 rubocop
[convention] 6-176: Module has too many lines. [138/100]
(Metrics/ModuleLength)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 111-111: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 125-125: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 148-148: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
@justin808 PR itself is ready. @grantspeelman Any ideas on reasons for that? |
@MUTOgen sorry, nothing comes to mind :( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @grantspeelman At the moment, we have 2 places:
I tried to remove the latter and pass project-specific VCR config using gem initializer (new option, like My question is: Is there any reason to have this config in
|
Don't see any issues with this approach 👍🏽 |
bacf5c5
to
99b53a3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (13)
lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js (2)
32-44
: Consider enhancing the fetch interceptor's robustnessWhile the implementation is functional, consider these improvements:
- Type checking for the options parameter
- Validation of the path parameter
- More specific error handling for JSON parsing
Here's a suggested enhancement:
- const fetch = (path, options, ...rest) => { + const fetch = (path, options = {}, ...rest) => { + if (!path || typeof path !== 'string') { + return originalFetch(path, options, ...rest); + } + if (options && options.body) { try { const body = JSON.parse(options.body); if (body.operationName) { return originalFetch(`${path}?operation=${body.operationName}`, options, ...rest); } - } catch (e) { + } catch (e) { + // Only log parsing errors, not structural ones + if (!(e instanceof SyntaxError)) { + console.error('GraphQL mock encountered an error:', e); + } return originalFetch(path, options, ...rest); } }
28-28
: Add comprehensive documentation for the GraphQL mock commandThe current comment is too brief. Consider adding documentation that explains:
- The purpose and use cases for this command
- How it integrates with VCR use_cassette
- Examples of usage in tests
- Any limitations or gotchas
Here's a suggested documentation block:
-// -- This is for Graphql usage. Add proxy-like mock to add operation name into query string -- +/** + * Custom command for GraphQL testing with VCR cassettes + * + * This command modifies the window.fetch behavior to include GraphQL operation names + * in the request URL, making it easier to match and record specific operations in + * VCR cassettes. + * + * @example + * // In your cypress test + * beforeEach(() => { + * cy.mockGraphQL(); + * }); + * + * it('fetches data', () => { + * // Your GraphQL operation will now include ?operation=OperationName in the URL + * cy.request('/graphql', { + * body: { + * operationName: 'GetUser', + * query: '...' + * } + * }); + * }); + * + * @note This should be used in conjunction with VCR use_cassette middleware + */README.md (3)
385-387
: Improve list formatting consistencyThe unordered list should use consistent markers throughout the document.
-It can be used in two modes: -- with separate insert/eject calls (more general, recommended way) -- with use_cassette wrapper (supports only GraphQL integration) +It can be used in two modes: +* with separate insert/eject calls (more general, recommended way) +* with use_cassette wrapper (supports only GraphQL integration)🧰 Tools
🪛 Markdownlint (0.37.0)
386-386: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
387-387: Expected: asterisk; Actual: dash
Unordered list style(MD004, ul-style)
501-505
: Add troubleshooting section for test stabilityGiven the reported issues with test stability and CI failures, consider adding a troubleshooting section to address common issues.
+### Troubleshooting VCR Integration + +#### Test Stability Issues + +If you encounter intermittent test failures with VCR: + +1. Ensure VCR configuration is not duplicated between the gem and project level +2. Configure VCR to ignore non-deterministic request headers: + ```ruby + c.vcr_options = { + hook_into: :webmock, + default_cassette_options: { + record: :once, + match_requests_on: [:method, :host, :path, :query] + }, + } + ``` +3. For CI environments, consider using `:once` record mode during development and `:none` in CI +4. Ensure your server is configured with a single worker and thread when using VCR
Line range hint
423-449
: Add best practices section for VCR usageThe example demonstrates basic VCR usage, but it would be helpful to include best practices for managing cassettes.
+### VCR Best Practices + +1. **Cassette Organization**: + ```js + // Group related requests in a single cassette + cy.vcr_insert_cassette('user_profile/update', { + record: "new_episodes", + match_requests_on: [:method, :host, :path, :query] + }) + ``` + +2. **Cassette Cleanup**: + ```js + // Ensure cassettes are always ejected + beforeEach(() => { + cy.app('clean') // includes VCR.eject_cassette + }) + + afterEach(() => { + cy.app('clean') + }) + ``` + +3. **Error Handling**: + ```js + // Handle VCR errors gracefully + Cypress.on('fail', (error, runnable) => { + if (error.message.includes('VCR')) { + cy.app('clean') + } + throw error + }) + ```🧰 Tools
🪛 Markdownlint (0.37.0)
425-425: null
Bare URL used(MD034, no-bare-urls)
lib/cypress_on_rails/vcr/middleware_helpers.rb (2)
28-34
: Consider validating VCR options before applying them.The
apply_vcr_options
method should validate options before application to prevent configuration errors.Consider adding validation:
def apply_vcr_options(config) + return unless configuration.vcr_options.is_a?(Hash) + configuration.vcr_options.each do |option, value| next if option.to_sym == :cassette_library_dir + unless option.respond_to?(:to_sym) + logger.warn "Invalid VCR option type: #{option.class}. Skipping." + next + end apply_vcr_option(config, option, value) end end
36-46
: Add logging for skipped VCR options.The
apply_vcr_option
method silently skips options that VCR doesn't support.Consider adding logging:
def apply_vcr_option(config, option, value) - return unless config.respond_to?(option) || config.respond_to?("#{option}=") + unless config.respond_to?(option) || config.respond_to?("#{option}=") + logger.warn "Unsupported VCR option: #{option}. Skipping." + return + end if config.respond_to?("#{option}=") config.send("#{option}=", value) elsif value.is_a?(Array) config.send(option, *value) else config.send(option, value) end endlib/cypress_on_rails/configuration.rb (2)
9-9
: Add documentation for new VCR configuration options.The new attributes lack documentation explaining their purpose and expected values.
Add RDoc documentation:
+ # @return [Boolean] Whether to use VCR's use_cassette middleware attr_accessor :use_vcr_use_cassette_middleware attr_accessor :before_request attr_accessor :logger + # @return [Hash] Options to pass to VCR.configure + # @example + # config.vcr_options = { hook_into: :webmock } attr_accessor :vcr_optionsAlso applies to: 12-12
37-37
: Consider type validation for VCR options.The reset method sets default values but doesn't ensure type safety when values are changed.
Consider adding type validation:
def reset self.api_prefix = '' self.install_folder = 'spec/e2e' self.use_middleware = true self.use_vcr_middleware = false self.use_vcr_use_cassette_middleware = false self.before_request = -> (request) {} self.logger = Logger.new(STDOUT) self.vcr_options = {} end +def vcr_options=(options) + unless options.nil? || options.is_a?(Hash) + logger.warn "vcr_options must be a Hash or nil, got: #{options.class}" + end + @vcr_options = options +endAlso applies to: 40-40
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (1)
47-53
: Enhance cassette name generation.The current implementation could be improved to:
- Better organize GraphQL cassettes by operation type
- Sanitize cassette names for filesystem safety
- Handle nested GraphQL operations
Consider this enhancement:
def fetch_request_cassette(request) + name = if request.path.start_with?('/graphql') + params = request.params + operation = params['operation'] + operation_type = params['operationName'] + "graphql/#{operation_type}/#{operation}" + else + request.path + end + sanitize_cassette_name(name) +end + +private + +def sanitize_cassette_name(name) + name.gsub(%r{[^0-9A-Za-z/\-_]}, '_').gsub(%r{/+}, '/') endspec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb (3)
20-115
: Refactor VCR insert tests using shared examples.The tests are comprehensive but contain repetitive structures. Consider using shared examples to improve maintainability.
Consider this refactoring:
RSpec.shared_examples "vcr insert request" do |cassette_name, options = {}| it "inserts cassette with correct options" do env['rack.input'] = rack_input([cassette_name, options]) aggregate_failures do expect(response).to eq([ 201, { 'Content-Type' => 'application/json' }, ['{"message":"OK"}'], ]) expect(vcr).to have_received(:turn_on!) expect(vcr).to have_received(:insert_cassette) .with(cassette_name, options.transform_keys(&:to_sym)) end end end # Usage it_behaves_like "vcr insert request", "cas1" it_behaves_like "vcr insert request", "cas1", { "record" => "new_episodes" }🧰 Tools
🪛 rubocop (1.69.1)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 111-111: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
116-152
: Refactor VCR eject tests using shared examples.Similar to the insert tests, the eject tests could benefit from shared examples.
Consider this refactoring:
RSpec.shared_examples "vcr eject error" do |error_class, message| it "handles #{error_class} with message" do allow(vcr).to receive(:eject_cassette).and_raise(error_class.new(message)) expect(response).to eq([ 500, { 'Content-Type' => 'application/json' }, [{ message: message }.to_json], ]) end end # Usage it_behaves_like "vcr eject error", ArgumentError, "No cassette to eject" it_behaves_like "vcr eject error", LoadError, "Cannot load VCR"🧰 Tools
🪛 rubocop (1.69.1)
[convention] 125-125: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 148-148: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
154-174
: Improve "Other paths" test organization.The tests for other paths could be more focused and better organized.
Consider this refactoring:
RSpec.shared_examples "non vcr path" do |path| it "handles #{path} correctly" do env['PATH_INFO'] = path expect(response).to eq([200, {}, ["app did #{path}"]]) expect(vcr).to have_received(:turn_off!) end end describe "Other paths" do %w[/ /__e2e__/login command /e2e_command].each do |path| it_behaves_like "non vcr path", path end end
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
README.md
(3 hunks)lib/cypress_on_rails/configuration.rb
(2 hunks)lib/cypress_on_rails/railtie.rb
(1 hunks)lib/cypress_on_rails/vcr/insert_eject_middleware.rb
(1 hunks)lib/cypress_on_rails/vcr/middleware_helpers.rb
(1 hunks)lib/cypress_on_rails/vcr/use_cassette_middleware.rb
(1 hunks)lib/cypress_on_rails/vcr_middleware.rb
(0 hunks)lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb
(1 hunks)lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js
(1 hunks)lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js
(1 hunks)spec/cypress_on_rails/configuration_spec.rb
(1 hunks)spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb
(1 hunks)spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb
(1 hunks)spec/cypress_on_rails/vcr_middleware_spec.rb
(0 hunks)specs_e2e/rails_3_2/config/boot.rb
(1 hunks)specs_e2e/rails_4_2/Gemfile
(1 hunks)
💤 Files with no reviewable changes (2)
- spec/cypress_on_rails/vcr_middleware_spec.rb
- lib/cypress_on_rails/vcr_middleware.rb
✅ Files skipped from review due to trivial changes (1)
- specs_e2e/rails_3_2/config/boot.rb
🚧 Files skipped from review as they are similar to previous changes (6)
- specs_e2e/rails_4_2/Gemfile
- lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js
- spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb
- lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb
- lib/cypress_on_rails/railtie.rb
- lib/cypress_on_rails/vcr/insert_eject_middleware.rb
🧰 Additional context used
🪛 Markdownlint (0.37.0)
README.md
386-386: Expected: asterisk; Actual: dash
Unordered list style
(MD004, ul-style)
387-387: Expected: asterisk; Actual: dash
Unordered list style
(MD004, ul-style)
🪛 rubocop (1.69.1)
spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb
[convention] 6-176: Module has too many lines. [138/100]
(Metrics/ModuleLength)
[convention] 31-31: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 43-43: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 54-54: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 65-65: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 76-76: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 89-89: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 100-100: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 111-111: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 125-125: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 138-138: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 148-148: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
🔇 Additional comments (6)
lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js (1)
29-47
: Why is this command commented out?
The implementation looks solid but is entirely commented out. Please clarify if this is intentional and what conditions need to be met before uncommenting it.
Would you like help creating integration tests to verify this functionality works correctly with VCR use_cassette?
lib/cypress_on_rails/vcr/middleware_helpers.rb (1)
13-15
: Consider making the cassette subdirectory configurable.
The hardcoded path "fixtures/vcr_cassettes" limits flexibility.
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (4)
14-19
:
Add error handling and uncomment VCR initialization.
The current implementation lacks error handling and has a commented-out VCR initialization that might be necessary.
Apply this diff:
def call(env)
return @app.call(env) if should_not_use_vcr?
- # initialize_vcr
- handle_request_with_vcr(env)
+ initialize_vcr
+ handle_request_with_vcr(env)
+rescue StandardError => e
+ [500, { 'Content-Type' => 'application/json' }, [{ message: e.message }.to_json]]
end
Likely invalid or redundant comment.
27-31
:
Fix VCR configuration checks.
The current implementation has several issues:
- Uses ActiveSupport's
present?
method which may not be available. - Accesses undefined
cassette_library_dir
.
Apply this diff:
def should_not_use_vcr?
vcr_defined? &&
- VCR.configuration.cassette_library_dir.present? &&
- VCR.configuration.cassette_library_dir != cassette_library_dir
+ !VCR.configuration.cassette_library_dir.to_s.empty? &&
+ VCR.configuration.cassette_library_dir != configuration.cassette_library_dir
end
Likely invalid or redundant comment.
33-45
:
Fix instance variable references and add logger configuration.
The code has incorrect instance variable references and undefined logger usage.
Apply this diff:
def initialize_vcr
WebMock.enable! if defined?(WebMock)
- vcr.turn_on!
+ @vcr.turn_on!
end
def handle_request_with_vcr(env)
request = Rack::Request.new(env)
cassette_name = fetch_request_cassette(request)
- vcr.use_cassette(cassette_name) do
- logger.info "Handle request with cassette name: #{cassette_name}"
+ @vcr.use_cassette(cassette_name) do
+ configuration.logger&.info "Handle request with cassette name: #{cassette_name}"
@app.call(env)
end
end
Likely invalid or redundant comment.
9-12
:
Add super call and validate VCR instance.
The initialize method needs to call super to ensure proper parent class initialization. Additionally, consider validating the VCR instance to prevent potential nil errors.
Apply this diff:
def initialize(app, vcr = nil)
+ super()
@app = app
+ raise ArgumentError, 'VCR instance is required' if vcr.nil?
@vcr = vcr
end
Likely invalid or redundant comment.
@MUTOgen why are you spending time on Rails 5.2. That's too old. |
@justin808 That's what we use for e2e tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (3)
14-19
: Consider thread safety in VCR initializationThe current implementation might face race conditions in multi-threaded environments where multiple requests could attempt to initialize VCR simultaneously.
Consider adding a thread-safe initialization mechanism:
def call(env) return @app.call(env) if should_not_use_vcr? - initialize_vcr + @vcr_initialized ||= Mutex.new.synchronize { initialize_vcr } handle_request_with_vcr(env) end
41-44
: Add error handling and logging improvementsThe current implementation lacks proper error handling and logging context.
Consider this enhancement:
-vcr.use_cassette(cassette_name) do - logger.info "Handle request with cassette name: #{cassette_name}" - @app.call(env) +vcr.use_cassette(cassette_name) do + logger&.info("VCR: Using cassette '#{cassette_name}' for #{request.request_method} #{request.path}") + begin + @app.call(env) + rescue => e + logger&.error("VCR: Error processing request with cassette '#{cassette_name}': #{e.message}") + raise + end end
47-53
: Enhance GraphQL cassette naming strategyThe current GraphQL cassette naming could be improved to handle more edge cases and provide better organization.
Consider this enhancement:
def fetch_request_cassette(request) - if request.path.start_with?('/graphql') && request.params.key?('operation') - "#{request.path}/#{request.params['operation']}" + if request.path.start_with?('/graphql') + operation = request.params['operation'] + variables = request.params['variables'] + "graphql/#{operation || 'anonymous'}/#{Digest::MD5.hexdigest(variables.to_s)}" else - request.path + request.path.sub(/^\//, '').tr('/', '_') end endThis improvement:
- Handles anonymous GraphQL operations
- Includes variables in the cassette name to differentiate between same operations with different variables
- Creates more filesystem-friendly cassette names
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
lib/cypress_on_rails/vcr/use_cassette_middleware.rb
(1 hunks)
🔇 Additional comments (2)
lib/cypress_on_rails/vcr/use_cassette_middleware.rb (2)
9-12
: Call super
in initialize method
The initialize method should call super
to ensure proper initialization of the parent class.
Apply this fix:
def initialize(app, vcr = nil)
+ super()
@app = app
@vcr = vcr
end
27-31
:
Fix undefined variable and Rails dependency
There are two issues in the should_not_use_vcr?
method:
cassette_library_dir
is undefinedpresent?
is a Rails-specific method
Apply these fixes:
def should_not_use_vcr?
vcr_defined? &&
- VCR.configuration.cassette_library_dir.present? &&
- VCR.configuration.cassette_library_dir != cassette_library_dir
+ !VCR.configuration.cassette_library_dir.to_s.empty? &&
+ VCR.configuration.cassette_library_dir != configuration.cassette_library_dir
end
Likely invalid or redundant comment.
2 successful runs in a row for a client project 🎉 I'm gonna keep an eye on it for a few days there 👀 |
WIP
Summary by CodeRabbit
New Features
Bug Fixes
bigdecimal
gem to prevent runtime errors.Tests
UseCassetteMiddleware
andInsertEjectMiddleware
to ensure correct functionality and error handling.Documentation