Skip to content

Commit

Permalink
cypress js plugin and vcr integration (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
grantspeelman authored Mar 8, 2022
1 parent a35dcd1 commit 17cd554
Show file tree
Hide file tree
Showing 165 changed files with 454 additions and 50 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- run: gem uninstall -v '>= 2' -ax bundler || true
- run: gem install bundler -v '< 2'
- name: Run interaction tests
run: ./spec/integrations/rails_3_2/test.sh
run: ./specs_e2e/rails_3_2/test.sh

rails_4_2:
runs-on: ubuntu-latest
Expand All @@ -39,7 +39,7 @@ jobs:
- run: gem uninstall -v '>= 2' -ax bundler || true
- run: gem install bundler -v '< 2'
- name: Run interaction tests
run: ./spec/integrations/rails_4_2/test.sh
run: ./specs_e2e/rails_4_2/test.sh

rails_5_2:
runs-on: ubuntu-latest
Expand All @@ -54,4 +54,4 @@ jobs:
- name: Run tests
run: bundle exec rake
- name: Run interaction tests
run: ./spec/integrations/rails_5_2/test.sh
run: ./specs_e2e/rails_5_2/test.sh
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ spec/examples.txt
spec/test.log
pkg/*.gem
vendor/bundle
.vscode
.vscode
node_modules
package-lock.json
yarn.lock
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## []

### Changed
* Add support for matching npm package and VCR

## [1.12.1]
[Compare]: https://github.com/shakacode/cypress-on-rails/compare/v1.12.0...v1.12.1

Expand Down
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,68 @@ describe('My First Test', function() {
})
```

## Expermintal Features (matching npm package)

Please test and give feedback

add the npm package:

```
yarn add cypress-on-rails --dev
```

### for VCR

#### setup

Add you VCR configuration to your `cypress_helper.rb`

```ruby
require 'vcr'
VCR.configure do |config|
config.hook_into :webmock
end
```

Add to you `cypress/support/index.js`

```js
import 'cypress-on-rails/support/index'
```

Add to you `clean.rb`

```ruby
VCR.eject_cassette # make sure we no cassettes inserted before the next test starts
```

#### usage

You have `vcr_insert_cassette` and `vcr_eject_cassette` available. https://www.rubydoc.info/github/vcr/vcr/VCR:insert_cassette


```js
describe('My First Test', function() {
beforeEach(() => { cy.app('load_seed') })

it('visit root', function() {
cy.app('clean') // have a look at cypress/app_commands/clean.rb

cy.vcr_insert_cassette('cats', { record: "new_episodes" })
cy.visit('/using_vcr/index')

cy.get('a').contains('Cats').click()
cy.contains('Wikipedia has a recording of a cat meowing, because why not?')

cy.vcr_eject_cassette();

cy.vcr_insert_cassette('cats')
cy.visit('/using_vcr/record_cats')
cy.contains('Wikipedia has a recording of a cat meowing, because why not?')
})
})
```

## Usage with other rack applications

Add CypressOnRails to your config.ru
Expand Down
1 change: 1 addition & 0 deletions cypress-on-rails.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rspec'
s.add_development_dependency 'railties', '>= 3.2'
s.add_development_dependency 'factory_bot'
s.add_development_dependency 'vcr'
s.metadata = {
"bug_tracker_uri" => "https://github.com/shakacode/cypress-on-rails/issues",
"changelog_uri" => "https://github.com/shakacode/cypress-on-rails/blob/master/CHANGELOG.md",
Expand Down
15 changes: 5 additions & 10 deletions lib/cypress_on_rails/middleware.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
require 'json'
require 'rack'
require 'cypress_on_rails/configuration'
require 'cypress_on_rails/middleware_config'
require 'cypress_on_rails/command_executor'

module CypressOnRails
# Middleware to handle cypress commands and eval
class Middleware
include MiddlewareConfig

def initialize(app, command_executor = CommandExecutor, file = ::File)
@app = app
@command_executor = command_executor
Expand All @@ -23,14 +25,6 @@ def call(env)

private

def configuration
CypressOnRails.configuration
end

def logger
configuration.logger
end

Command = Struct.new(:name, :options, :cypress_folder) do
# @return [Array<Cypress::Middleware::Command>]
def self.from_body(body, configuration)
Expand Down Expand Up @@ -71,7 +65,8 @@ def handle_command(req)
[500, {'Content-Type' => 'application/json'}, [output]]
end
else
[404, {}, ["could not find command file: #{missing_command.file_path}"]]
output = {"message" => "could not find command file: #{missing_command.file_path}"}.to_json
[404, {'Content-Type' => 'application/json'}, [output]]
end
end
end
Expand Down
17 changes: 17 additions & 0 deletions lib/cypress_on_rails/middleware_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'json'
require 'rack'
require 'cypress_on_rails/configuration'

module CypressOnRails
module MiddlewareConfig
protected

def configuration
CypressOnRails.configuration
end

def logger
configuration.logger
end
end
end
4 changes: 3 additions & 1 deletion lib/cypress_on_rails/railtie.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
require 'rails/railtie'
require 'cypress_on_rails/configuration'
require 'cypress_on_rails/middleware'

module CypressOnRails
class Railtie < Rails::Railtie
initializer :setup_cypress_middleware, after: :load_config_initializers do |app|
if CypressOnRails.configuration.use_middleware?
require 'cypress_on_rails/middleware'
app.middleware.use Middleware
require 'cypress_on_rails/vcr_middleware'
app.middleware.use VCRMiddleware
end
end
end
Expand Down
60 changes: 60 additions & 0 deletions lib/cypress_on_rails/vcr_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'json'
require 'rack'
require 'cypress_on_rails/middleware_config'

module CypressOnRails
# Middleware to handle vcr
class VCRMiddleware
include MiddlewareConfig

def initialize(app, vcr = nil)
@app = app
@vcr = vcr
end

def call(env)
request = Rack::Request.new(env)
if request.path.start_with?('/__cypress__/vcr/insert')
configuration.tagged_logged { handle_insert(request) }
elsif request.path.start_with?('/__cypress__/vcr/eject')
configuration.tagged_logged { handle_eject }
else
@app.call(env)
end
end

private

def handle_insert(req)
body = JSON.parse(req.body.read)
logger.info "vcr insert cassette: #{body}"
cassette_name = body[0]
options = (body[1] || {}).symbolize_keys
options[:record] = options[:record].to_sym if options[:record]
options[:match_requests_on] = options[:match_requests_on].map(&:to_sym) if options[:match_requests_on]
options[:serialize_with] = options[:serialize_with].to_sym if options[:serialize_with]
options[:persist_with] = options[:persist_with].to_sym if options[:persist_with]
vcr.insert_cassette(cassette_name, options)
[201, {'Content-Type' => 'application/json'}, [{'message': 'OK'}.to_json]]
rescue LoadError, ArgumentError => e
[501, {'Content-Type' => 'application/json'}, [{'message': e.message}.to_json]]
end

def handle_eject
logger.info "vcr eject cassette"
vcr.eject_cassette
[201, {'Content-Type' => 'application/json'}, [{'message': 'OK'}.to_json]]
rescue LoadError, ArgumentError => e
[501, {'Content-Type' => 'application/json'}, [{'message': e.message}.to_json]]
end

def vcr
return @vcr if @vcr
require 'vcr'
VCR.configure do |config|
config.cassette_library_dir = "#{configuration.cypress_folder}/fixtures/vcr_cassettes"
end
@vcr = VCR
end
end
end
43 changes: 21 additions & 22 deletions lib/generators/cypress_on_rails/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,37 @@ class InstallGenerator < Rails::Generators::Base
class_option :install_cypress, type: :boolean, default: true
class_option :install_cypress_with, type: :string, default: 'yarn'
class_option :install_cypress_examples, type: :boolean, default: false
class_option :experimental, type: :boolean, default: false
source_root File.expand_path('../templates', __FILE__)

def install_cypress
if !Dir.exists?(options.cypress_folder) || Dir["#{options.cypress_folder}/*"].empty?
directories = options.cypress_folder.split('/')
directories.pop
install_dir = "#{Dir.pwd}/#{directories.join('/')}"
command = nil
if options.install_cypress
if options.install_cypress_with == 'yarn'
command = "yarn --cwd=#{install_dir} add cypress --dev"
elsif options.install_cypress_with == 'npm'
command = "cd #{install_dir}; npm install cypress --save-dev"
end
if command
say command
fail 'failed to install cypress' unless system(command)
end
directories = options.cypress_folder.split('/')
directories.pop
install_dir = "#{Dir.pwd}/#{directories.join('/')}"
command = nil
if options.install_cypress
if options.install_cypress_with == 'yarn'
command = "yarn --cwd=#{install_dir} add cypress --dev"
elsif options.install_cypress_with == 'npm'
command = "cd #{install_dir}; npm install cypress --save-dev"
end
if options.install_cypress_examples
directory 'spec/cypress/integration/examples', "#{options.cypress_folder}/integration/examples"
directory 'spec/cypress/fixtures', "#{options.cypress_folder}/fixtures"
if command
say command
fail 'failed to install cypress' unless system(command)
end
copy_file "spec/cypress/support/index.js", "#{options.cypress_folder}/support/index.js"
copy_file "spec/cypress/support/commands.js", "#{options.cypress_folder}/support/commands.js"
copy_file "spec/cypress.json", "#{options.cypress_folder}/../cypress.json"
end
if options.install_cypress_examples
directory 'spec/cypress/integration/examples', "#{options.cypress_folder}/integration/examples"
directory 'spec/cypress/fixtures', "#{options.cypress_folder}/fixtures"
end
template "spec/cypress/support/index.js.erb", "#{options.cypress_folder}/support/index.js"
copy_file "spec/cypress/support/commands.js", "#{options.cypress_folder}/support/commands.js"
copy_file "spec/cypress.json", "#{options.cypress_folder}/../cypress.json"
end

def add_initial_files
template "config/initializers/cypress_on_rails.rb.erb", "config/initializers/cypress_on_rails.rb"
copy_file "spec/cypress/cypress_helper.rb", "#{options.cypress_folder}/cypress_helper.rb"
template "spec/cypress/cypress_helper.rb.erb", "#{options.cypress_folder}/cypress_helper.rb"
copy_file "spec/cypress/support/on-rails.js", "#{options.cypress_folder}/support/on-rails.js"
directory 'spec/cypress/app_commands', "#{options.cypress_folder}/app_commands"
directory 'spec/cypress/integration/rails_examples', "#{options.cypress_folder}/integration/rails_examples"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@

CypressOnRails::SmartFactoryWrapper.reload

if defined?(VCR)
VCR.eject_cassette # make sure we any cassettes inserted before the next test starts
end

Rails.logger.info "APPCLEANED" # used by log_fail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,8 @@
Rails.root.join('spec', 'factories', '**', '*.rb')
]
)

<% unless options.experimental %># <% end %>require 'vcr'
<% unless options.experimental %># <% end %>VCR.configure do |config|
<% unless options.experimental %># <% end %> config.hook_into :webmock
<% unless options.experimental %># <% end %>end
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe('Rails Other examples', function() {
it('Inserting a cassette', function() {
cy.app('clean') // have a look at cypress/app_commands/clean.rb

cy.vcr_insert_cassette('cats', { record: "new_episodes" })
cy.visit('/using_vcr/index')

cy.get('a').contains('Cats').click()
cy.contains('Wikipedia has a recording of a cat meowing, because why not?')

cy.vcr_eject_cassette();

cy.vcr_insert_cassette('cats')
cy.visit('/using_vcr/record_cats')
cy.contains('Wikipedia has a recording of a cat meowing, because why not?')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// ***********************************************************

// Import commands.js using ES2015 syntax:
<% unless options.experimental %>// <% end %>import 'cypress-on-rails/support/index'
import './commands'
import './on-rails'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Cypress.Commands.add('appCommands', function (body) {
}).then((response) => {
log.end();
if (response.status !== 201) {
expect(response.body.message).to.be.empty
expect(response.body.message).to.equal('')
expect(response.status).to.be.equal(201)
}
return response.body
Expand Down
1 change: 1 addition & 0 deletions plugin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
4 changes: 4 additions & 0 deletions plugin/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// export a function
module.exports = (on, config) => {
// configure plugins here
}
Loading

0 comments on commit 17cd554

Please sign in to comment.