├── test
├── dummy
│ ├── log
│ │ └── .keep
│ ├── lib
│ │ └── assets
│ │ │ └── .keep
│ ├── public
│ │ ├── favicon.ico
│ │ ├── apple-touch-icon.png
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── 500.html
│ │ ├── 422.html
│ │ └── 404.html
│ ├── app
│ │ ├── assets
│ │ │ ├── images
│ │ │ │ └── .keep
│ │ │ ├── javascripts
│ │ │ │ ├── channels
│ │ │ │ │ └── .keep
│ │ │ │ ├── examples.js
│ │ │ │ ├── cable.js
│ │ │ │ └── application.js
│ │ │ ├── config
│ │ │ │ └── manifest.js
│ │ │ └── stylesheets
│ │ │ │ ├── examples.css
│ │ │ │ ├── application.css
│ │ │ │ └── scaffold.css
│ │ ├── models
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ ├── example.rb
│ │ │ └── application_record.rb
│ │ ├── controllers
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ ├── application_controller.rb
│ │ │ └── examples_controller.rb
│ │ ├── views
│ │ │ ├── layouts
│ │ │ │ ├── mailer.text.erb
│ │ │ │ ├── mailer.html.erb
│ │ │ │ └── application.html.erb
│ │ │ └── examples
│ │ │ │ ├── new.html.erb
│ │ │ │ ├── edit.html.erb
│ │ │ │ ├── show.html.erb
│ │ │ │ ├── index.html.erb
│ │ │ │ └── _form.html.erb
│ │ ├── helpers
│ │ │ ├── examples_helper.rb
│ │ │ └── application_helper.rb
│ │ ├── jobs
│ │ │ └── application_job.rb
│ │ ├── channels
│ │ │ └── application_cable
│ │ │ │ ├── channel.rb
│ │ │ │ └── connection.rb
│ │ └── mailers
│ │ │ └── application_mailer.rb
│ ├── package.json
│ ├── config
│ │ ├── environments
│ │ │ ├── system_tester.rb
│ │ │ ├── test.rb
│ │ │ ├── development.rb
│ │ │ └── production.rb
│ │ ├── routes.rb
│ │ ├── spring.rb
│ │ ├── environment.rb
│ │ ├── initializers
│ │ │ ├── mime_types.rb
│ │ │ ├── application_controller_renderer.rb
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── cookies_serializer.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── wrap_parameters.rb
│ │ │ ├── cors.rb
│ │ │ ├── assets.rb
│ │ │ └── inflections.rb
│ │ ├── cable.yml
│ │ ├── boot.rb
│ │ ├── application.rb
│ │ ├── database.yml
│ │ ├── locales
│ │ │ └── en.yml
│ │ ├── secrets.yml
│ │ └── puma.rb
│ ├── bin
│ │ ├── rake
│ │ ├── bundle
│ │ ├── rails
│ │ ├── yarn
│ │ ├── update
│ │ └── setup
│ ├── config.ru
│ ├── Rakefile
│ ├── db
│ │ ├── migrate
│ │ │ └── 20170624013811_create_examples.rb
│ │ └── schema.rb
│ └── test
│ │ └── test_helper.rb
├── fabricators
│ └── system_tester
│ │ ├── stair_step_fabricator.rb
│ │ ├── scenario_step_fabricator.rb
│ │ ├── stair_fabricator.rb
│ │ ├── feature_fabricator.rb
│ │ ├── scenario_fabricator.rb
│ │ └── step_fabricator.rb
├── system_tester_test.rb
├── integration
│ └── system_tester
│ │ ├── status_controller_test.rb
│ │ ├── step_types_controller_test.rb
│ │ ├── executions_controller_test.rb
│ │ ├── stair_steps_controller_test.rb
│ │ ├── features_controller_test.rb
│ │ ├── scenario_steps_controller_test.rb
│ │ ├── scenarios_controller_test.rb
│ │ └── steps_controller_test.rb
├── models
│ └── system_tester
│ │ └── command_handler_test.rb
└── test_helper.rb
├── lib
├── system_tester
│ ├── version.rb
│ └── engine.rb
├── system_tester.rb
└── tasks
│ └── system_tester_tasks.rake
├── screenshot.png
├── app
├── jobs
│ └── system_tester
│ │ └── application_job.rb
├── channels
│ ├── application_cable
│ │ ├── channel.rb
│ │ └── connection.rb
│ └── system_tester
│ │ └── execution_channel.rb
├── models
│ ├── system_tester
│ │ ├── application_record.rb
│ │ ├── action.rb
│ │ ├── assertion.rb
│ │ ├── click_on.rb
│ │ ├── assert_text.rb
│ │ ├── stair_step.rb
│ │ ├── scenario_step.rb
│ │ ├── select.rb
│ │ ├── fill_in.rb
│ │ ├── assert_selector.rb
│ │ ├── command_handler.rb
│ │ ├── scenario.rb
│ │ ├── visit.rb
│ │ ├── feature.rb
│ │ ├── stair.rb
│ │ └── step.rb
│ └── concerns
│ │ └── system_tester
│ │ ├── title_validatable.rb
│ │ └── fileable.rb
└── controllers
│ └── system_tester
│ ├── status_controller.rb
│ ├── step_types_controller.rb
│ ├── application_controller.rb
│ ├── executions_controller.rb
│ ├── stair_steps_controller.rb
│ ├── features_controller.rb
│ ├── scenario_steps_controller.rb
│ ├── scenarios_controller.rb
│ └── steps_controller.rb
├── .byebug_history
├── .gitignore
├── db
├── migrate
│ ├── 20170513131150_create_system_tester_features.rb
│ ├── 20170513213953_create_system_tester_scenarios.rb
│ ├── 20170513214255_create_system_tester_steps.rb
│ ├── 20170629120850_create_system_tester_stair_steps.rb
│ └── 20170513214722_create_system_tester_scenario_steps.rb
└── schema.rb
├── bin
└── rails
├── Gemfile
├── Rakefile
├── config
└── routes.rb
├── system_tester.gemspec
├── .travis.yml
├── MIT-LICENSE
├── README.md
└── Gemfile.lock
/test/dummy/log/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/lib/assets/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/images/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/models/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/channels/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/mailer.text.erb:
--------------------------------------------------------------------------------
1 | <%= yield %>
2 |
--------------------------------------------------------------------------------
/test/dummy/app/helpers/examples_helper.rb:
--------------------------------------------------------------------------------
1 | module ExamplesHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test/dummy/app/models/example.rb:
--------------------------------------------------------------------------------
1 | class Example < ApplicationRecord
2 | end
3 |
--------------------------------------------------------------------------------
/test/dummy/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/lib/system_tester/version.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | VERSION = '0.3.0'
3 | end
4 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rlafranchi/system_tester/HEAD/screenshot.png
--------------------------------------------------------------------------------
/test/dummy/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | end
3 |
--------------------------------------------------------------------------------
/test/dummy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dummy",
3 | "private": true,
4 | "dependencies": {}
5 | }
6 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/system_tester.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | config.schema_format = :sql
3 | end
--------------------------------------------------------------------------------
/app/jobs/system_tester/application_job.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ApplicationJob < ActiveJob::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test/dummy/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative '../config/boot'
3 | require 'rake'
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/test/dummy/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Channel < ActionCable::Channel::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Connection < ActionCable::Connection::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test/dummy/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Channel < ActionCable::Channel::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test/fabricators/system_tester/stair_step_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:stair_step, from: 'SystemTester::StairStep') do
2 | step
3 | stair
4 | end
--------------------------------------------------------------------------------
/test/dummy/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | resources :examples
3 | mount SystemTester::Engine => "/system_tester"
4 | end
5 |
--------------------------------------------------------------------------------
/test/dummy/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Connection < ActionCable::Connection::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test/fabricators/system_tester/scenario_step_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:scenario_step, from: 'SystemTester::ScenarioStep') do
2 | step
3 | scenario
4 | end
--------------------------------------------------------------------------------
/test/fabricators/system_tester/stair_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:stair, from: 'SystemTester::Stair') do
2 | title { Faker::Lorem.words(2).join(" ") }
3 | end
--------------------------------------------------------------------------------
/test/dummy/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 |
2 | //= link_tree ../images
3 | //= link_directory ../javascripts .js
4 | //= link_directory ../stylesheets .css
5 |
6 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery with: :exception
3 | end
4 |
--------------------------------------------------------------------------------
/test/dummy/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | class ApplicationMailer < ActionMailer::Base
2 | default from: 'from@example.com'
3 | layout 'mailer'
4 | end
5 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/new.html.erb:
--------------------------------------------------------------------------------
1 |
New Example
2 |
3 | <%= render 'form', example: @example %>
4 |
5 | <%= link_to 'Back', examples_path %>
6 |
--------------------------------------------------------------------------------
/test/dummy/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/test/dummy/config/spring.rb:
--------------------------------------------------------------------------------
1 | %w(
2 | .ruby-version
3 | .rbenv-vars
4 | tmp/restart.txt
5 | tmp/caching-dev.txt
6 | ).each { |path| Spring.watch(path) }
7 |
--------------------------------------------------------------------------------
/test/fabricators/system_tester/feature_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:feature, from: 'SystemTester::Feature') do
2 | title { Faker::Lorem.words(2).join(" ") }
3 | end
--------------------------------------------------------------------------------
/test/dummy/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative 'config/environment'
4 |
5 | run Rails.application
6 |
--------------------------------------------------------------------------------
/lib/system_tester.rb:
--------------------------------------------------------------------------------
1 | require "rack/cors"
2 | require "acts_as_list"
3 | require "system_tester/engine"
4 |
5 | module SystemTester
6 | # Your code goes here...
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path('../config/application', __dir__)
3 | require_relative '../config/boot'
4 | require 'rails/commands'
5 |
--------------------------------------------------------------------------------
/test/fabricators/system_tester/scenario_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:scenario, from: 'SystemTester::Scenario') do
2 | title { Faker::Lorem.words(2).join(" ") }
3 | feature
4 | end
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/examples.css:
--------------------------------------------------------------------------------
1 | /*
2 | Place all the styles related to the matching controller here.
3 | They will automatically be included in application.css.
4 | */
5 |
--------------------------------------------------------------------------------
/test/system_tester_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class SystemTester::Test < ActiveSupport::TestCase
4 | test "truth" do
5 | assert_kind_of Module, SystemTester
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/examples.js:
--------------------------------------------------------------------------------
1 | // Place all the behaviors and hooks related to the matching controller here.
2 | // All this logic will automatically be available in application.js.
3 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/edit.html.erb:
--------------------------------------------------------------------------------
1 | Editing Example
2 |
3 | <%= render 'form', example: @example %>
4 |
5 | <%= link_to 'Show', @example %> |
6 | <%= link_to 'Back', examples_path %>
7 |
--------------------------------------------------------------------------------
/test/dummy/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative 'application'
3 | require 'rack/cors'
4 |
5 | # Initialize the Rails application.
6 | Rails.application.initialize!
7 |
--------------------------------------------------------------------------------
/app/models/system_tester/application_record.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ApplicationRecord < ActiveRecord::Base
3 | self.abstract_class = true
4 | establish_connection :system_tester
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/.byebug_history:
--------------------------------------------------------------------------------
1 | continue
2 | file_name_was
3 | full_file
4 | file_name
5 | base_path
6 | continue
7 | test_path.join(base_path)
8 | test_path.join(base_dir)
9 | base_path
10 | bas_path
11 | test_path
12 | full_file
13 |
--------------------------------------------------------------------------------
/app/channels/system_tester/execution_channel.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ExecutionChannel < ApplicationCable::Channel
3 | def subscribed
4 | stream_from "system_tester_execution"
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: async
6 |
7 | production:
8 | adapter: redis
9 | url: redis://localhost:6379/1
10 | channel_prefix: dummy_production
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle/
2 | log/*.log
3 | pkg/
4 | test/dummy/db/*.sqlite3
5 | test/dummy/db/*.sqlite3-journal
6 | test/dummy/log/*.log
7 | test/dummy/tmp/
8 | test/dummy/test/support/
9 | test/dummy/test/system/
10 | .idea/
11 | coverage/
12 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ApplicationController.renderer.defaults.merge!(
4 | # http_host: 'example.org',
5 | # https: false
6 | # )
7 |
--------------------------------------------------------------------------------
/test/fabricators/system_tester/step_fabricator.rb:
--------------------------------------------------------------------------------
1 | Fabricator(:step, from: 'SystemTester::Step') do
2 | title { Faker::Lorem.words(2).join(" ") }
3 | arg_one { Faker::Lorem.words(2).join(" ") }
4 | arg_two { Faker::Lorem.words(2).join(" ") }
5 | end
--------------------------------------------------------------------------------
/test/dummy/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/test/dummy/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative 'config/application'
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/db/migrate/20170513131150_create_system_tester_features.rb:
--------------------------------------------------------------------------------
1 | class CreateSystemTesterFeatures < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :system_tester_features do |t|
4 | t.string :title
5 | t.timestamps
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/dummy/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Set up gems listed in the Gemfile.
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
3 |
4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5 | $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
6 |
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20170624013811_create_examples.rb:
--------------------------------------------------------------------------------
1 | class CreateExamples < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :examples do |t|
4 | t.string :title
5 | t.text :comment
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/status_controller.rb:
--------------------------------------------------------------------------------
1 | require 'system_tester/version'
2 | module SystemTester
3 | class StatusController < ApplicationController
4 |
5 | def index
6 | render json: {status: "OK", version: SystemTester::VERSION}
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/models/concerns/system_tester/title_validatable.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | module TitleValidatable
3 | extend ActiveSupport::Concern
4 |
5 | included do
6 | validates_presence_of :title
7 | validates_format_of :title, with: /\A[a-zA-Z\s]*\z/
8 | end
9 | end
10 | end
--------------------------------------------------------------------------------
/app/models/system_tester/action.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Action < Step
3 | def to_s
4 | "#{INDENT}# Action: #{commented_title}\n"
5 | end
6 |
7 | def self.bg_css
8 | "orange"
9 | end
10 |
11 | def icon
12 | "input"
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/models/system_tester/assertion.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Assertion < Step
3 | def to_s
4 | "#{INDENT}# Assertion: #{commented_title}\n"
5 | end
6 |
7 | def self.bg_css
8 | "green"
9 | end
10 |
11 | def icon
12 | "done"
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/mailer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/db/migrate/20170513213953_create_system_tester_scenarios.rb:
--------------------------------------------------------------------------------
1 | class CreateSystemTesterScenarios < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :system_tester_scenarios do |t|
4 | t.string :title
5 | t.references :system_tester_feature, foreign_key: true
6 | t.timestamps
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20170513214255_create_system_tester_steps.rb:
--------------------------------------------------------------------------------
1 | class CreateSystemTesterSteps < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :system_tester_steps do |t|
4 | t.string :title
5 | t.string :type
6 | t.string :arg_one
7 | t.string :arg_two
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/show.html.erb:
--------------------------------------------------------------------------------
1 | <%= notice %>
2 |
3 |
4 | Title:
5 | <%= @example.title %>
6 |
7 |
8 |
9 | Comment:
10 | <%= @example.comment %>
11 |
12 |
13 | <%= link_to 'Edit', edit_example_path(@example) %> |
14 | <%= link_to 'Back', examples_path %>
15 |
--------------------------------------------------------------------------------
/test/dummy/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../../config/environment', __FILE__)
2 | require 'rails/test_help'
3 |
4 | class ActiveSupport::TestCase
5 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
6 | fixtures :all
7 |
8 | # Add more helper methods to be used by all tests here...
9 | end
10 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/step_types_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class StepTypesController < ApplicationController
5 | def index
6 | render json: Step.leafs
7 | end
8 |
9 | def parents
10 | render json: Step.parent_types
11 | end
12 | end
13 | end
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dummy
5 | <%= csrf_meta_tags %>
6 |
7 | <%= stylesheet_link_tag 'application', media: 'all' %>
8 | <%= javascript_include_tag 'application' %>
9 |
10 |
11 |
12 | <%= yield %>
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/application_controller.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ApplicationController < ActionController::API
3 | # protect_from_forgery with: :exception
4 |
5 | # before_action :view_headers
6 | #
7 | # private
8 | #
9 | # def view_headers
10 | # Rails.logger.debug request.env
11 | # end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/test/dummy/bin/yarn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | VENDOR_PATH = File.expand_path('..', __dir__)
3 | Dir.chdir(VENDOR_PATH) do
4 | begin
5 | exec "yarnpkg #{ARGV.join(" ")}"
6 | rescue Errno::ENOENT
7 | $stderr.puts "Yarn executable was not detected in the system."
8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
9 | exit 1
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20170629120850_create_system_tester_stair_steps.rb:
--------------------------------------------------------------------------------
1 | class CreateSystemTesterStairSteps < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :system_tester_stair_steps do |t|
4 | t.integer :position
5 | t.references :system_tester_step, foreign_key: true
6 | t.references :system_tester_stair, foreign_key: { to_table: :system_tester_steps }
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/system_tester/click_on.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ClickOn < Action
3 | def to_s
4 | "#{super}#{INDENT}click_on \"#{arg_one}\"\n\n"
5 | end
6 |
7 | def self.friendly_type
8 | "Click"
9 | end
10 |
11 | def self.args
12 | [
13 | {
14 | name: 'arg_one',
15 | label: 'Element',
16 | type: 'text'
17 | }
18 | ]
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/test/integration/system_tester/status_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class StatusControllerTest < ActionDispatch::IntegrationTest
5 | test "#index" do
6 | get "/system_tester/status"
7 | assert_equal "OK", JSON.parse(response.body)["status"]
8 | assert_equal SystemTester::VERSION, JSON.parse(response.body)["version"]
9 | assert_response :success
10 | end
11 | end
12 | end
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/cable.js:
--------------------------------------------------------------------------------
1 | // Action Cable provides the framework to deal with WebSockets in Rails.
2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command.
3 | //
4 | //= require action_cable
5 | //= require_self
6 | //= require_tree ./channels
7 |
8 | (function() {
9 | this.App || (this.App = {});
10 |
11 | App.cable = ActionCable.createConsumer();
12 |
13 | }).call(this);
14 |
--------------------------------------------------------------------------------
/app/models/system_tester/assert_text.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class AssertText < Assertion
3 | def to_s
4 | "#{super}#{INDENT}assert_text \"#{arg_one}\"\n\n"
5 | end
6 |
7 | def self.friendly_type
8 | "Text"
9 | end
10 |
11 | def self.args
12 | [
13 | {
14 | name: 'arg_one',
15 | label: 'Text',
16 | type: 'text'
17 | }
18 | ]
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/db/migrate/20170513214722_create_system_tester_scenario_steps.rb:
--------------------------------------------------------------------------------
1 | class CreateSystemTesterScenarioSteps < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :system_tester_scenario_steps do |t|
4 | t.integer :position
5 | t.references :system_tester_step, foreign_key: true
6 | t.references :system_tester_scenario, foreign_key: true, index: {name: "index_st_st_scenario_id"}
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/app/models/system_tester/stair_step.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class StairStep < ApplicationRecord
3 | belongs_to :step, class_name: "SystemTester::Step", foreign_key: "system_tester_step_id"
4 | belongs_to :stair, class_name: "SystemTester::Stair", foreign_type: "SystemTester::Stair", foreign_key: "system_tester_stair_id"
5 | acts_as_list scope: :system_tester_stair_id
6 |
7 | after_commit do
8 | stair.touch if stair.present?
9 | end
10 | end
11 | end
--------------------------------------------------------------------------------
/app/models/system_tester/scenario_step.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ScenarioStep < ApplicationRecord
3 | belongs_to :step, class_name: "SystemTester::Step", foreign_key: "system_tester_step_id"
4 | belongs_to :scenario, class_name: "SystemTester::Scenario", foreign_key: "system_tester_scenario_id"
5 | acts_as_list scope: :system_tester_scenario_id
6 |
7 | after_commit do
8 | scenario.feature.touch if scenario.present? && scenario.feature.present?
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/models/system_tester/select.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Select < Action
3 | def to_s
4 | "#{super}#{INDENT}select \"#{arg_one}\", from: \"#{arg_two}\"\n\n"
5 | end
6 |
7 | def self.friendly_type
8 | "Select"
9 | end
10 |
11 | def self.args
12 | [
13 | {
14 | name: 'arg_two',
15 | label: 'Select Label',
16 | type: 'text'
17 | },
18 | {
19 | name: 'arg_one',
20 | label: 'Option',
21 | type: 'text'
22 | }
23 | ]
24 | end
25 | end
26 | end
--------------------------------------------------------------------------------
/app/models/system_tester/fill_in.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class FillIn < Action
3 | def to_s
4 | "#{super}#{INDENT}fill_in \"#{arg_one}\", with: \"#{arg_two}\"\n\n"
5 | end
6 |
7 | def self.friendly_type
8 | "Fill"
9 | end
10 |
11 | def self.args
12 | [
13 | {
14 | name: 'arg_one',
15 | label: 'Input Label',
16 | type: 'text'
17 | },
18 | {
19 | name: 'arg_two',
20 | label: 'Text',
21 | type: 'text'
22 | }
23 | ]
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/test/dummy/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative 'boot'
2 |
3 | require 'rails/all'
4 |
5 | Bundler.require(*Rails.groups)
6 | require "system_tester"
7 |
8 | module Dummy
9 | class Application < Rails::Application
10 | # Initialize configuration defaults for originally generated Rails version.
11 | config.load_defaults 5.1
12 |
13 | # Settings in config/environments/* take precedence over those specified here.
14 | # Application configuration should go into files in config/initializers
15 | # -- all .rb files in that directory are automatically loaded.
16 | end
17 | end
18 |
19 |
--------------------------------------------------------------------------------
/app/models/system_tester/assert_selector.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class AssertSelector < Assertion
3 | def to_s
4 | "#{super}#{INDENT}assert_selector \"#{arg_one}\", text: \"#{arg_two}\"\n\n"
5 | end
6 |
7 | def self.friendly_type
8 | "Selector"
9 | end
10 |
11 | def self.args
12 | [
13 | {
14 | name: 'arg_one',
15 | label: 'Selector',
16 | type: 'text'
17 | },
18 | {
19 | name: 'arg_two',
20 | label: 'Text',
21 | type: 'text'
22 | }
23 | ]
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails gems
3 | # installed from the root of your application.
4 |
5 | ENGINE_ROOT = File.expand_path('../..', __FILE__)
6 | ENGINE_PATH = File.expand_path('../../lib/system_tester/engine', __FILE__)
7 | APP_PATH = File.expand_path('../../test/dummy/config/application', __FILE__)
8 |
9 | # Set up gems listed in the Gemfile.
10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
11 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
12 |
13 | require 'rails/all'
14 | require 'rails/engine/commands'
15 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/cors.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Avoid CORS issues when API is called from the frontend app.
4 | # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
5 |
6 | # Read more: https://github.com/cyu/rack-cors
7 | #
8 | # Rails.application.config.middleware.insert_before 0, Rack::Cors do
9 | # allow do
10 | # origins 'http://localhost:8080', 'chrome-extension://ebpjncfolmfiiphibdajgblbchkklbcf/*'
11 | #
12 | # resource '*',
13 | # headers: :any,
14 | # methods: [:get, :post, :put, :patch, :delete, :options, :head]
15 | # end
16 | # end
17 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
--------------------------------------------------------------------------------
/test/integration/system_tester/step_types_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class SteptypesControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | Dir.glob(SystemTester::Engine.root.join("app", "models" , "**", "*.rb")).each do |dep|
7 | require_dependency dep
8 | end
9 | end
10 |
11 | test"#index" do
12 | get "/system_tester/step_types"
13 | assert JSON.parse(response.body).length > 0
14 | assert_response :success
15 | end
16 |
17 | test "#parents" do
18 | get "/system_tester/step_types/parents"
19 | assert JSON.parse(response.body).length > 0
20 | assert_response :success
21 | end
22 | end
23 | end
--------------------------------------------------------------------------------
/test/models/system_tester/command_handler_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class CommandHandlerTest < ActiveSupport::TestCase
5 | test "#run" do
6 | ch = SystemTester::CommandHandler.new("echo 'hello'")
7 | result = ""
8 | ch.run do |c|
9 | result << c
10 | end
11 | assert_equal 0, ch.status
12 | assert_match "hello", result
13 | end
14 |
15 | test "#run_each_line" do
16 | ch = SystemTester::CommandHandler.new("echo 'hello'")
17 | result = ""
18 | ch.run_each_line do |line|
19 | result << line
20 | end
21 | assert_equal 0, ch.status
22 | assert_match "hello", result
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file. JavaScript code in this file should be added after the last require_* statement.
9 | //
10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | //= require_tree .
14 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/index.html.erb:
--------------------------------------------------------------------------------
1 | <%= notice %>
2 |
3 | Examples
4 |
5 |
6 |
7 |
8 | | Title |
9 | Comment |
10 | |
11 |
12 |
13 |
14 |
15 | <% @examples.each do |example| %>
16 |
17 | | <%= example.title %> |
18 | <%= example.comment %> |
19 | <%= link_to 'Show', example %> |
20 | <%= link_to 'Edit', edit_example_path(example) %> |
21 | <%= link_to 'Destroy', example, method: :delete, data: { confirm: 'Are you sure?' } %> |
22 |
23 | <% end %>
24 |
25 |
26 |
27 |
28 |
29 | <%= link_to 'New Example', new_example_path %>
30 |
--------------------------------------------------------------------------------
/test/dummy/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development.sqlite3
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test.sqlite3
22 |
23 | production:
24 | <<: *default
25 | database: db/production.sqlite3
26 |
27 | system_tester:
28 | <<: *default
29 | database: db/system_tester.sqlite3
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Declare your gem's dependencies in system_tester.gemspec.
4 | # Bundler will treat runtime dependencies like base dependencies, and
5 | # development dependencies will be added by default to the :development group.
6 | gemspec
7 |
8 | # Declare any dependencies that are still in development here instead of in
9 | # your gemspec. These might include edge Rails or gems from your path or
10 | # Git. Remember to move these dependencies to your gemspec before releasing
11 | # your gem to rubygems.org.
12 |
13 | # To use a debugger
14 | gem 'byebug', group: [:development, :test]
15 | gem 'rack-cors', require: 'rack/cors', group: [:development, :test]
16 |
17 | group :test do
18 | gem 'simplecov'
19 | gem 'codeclimate-test-reporter', '~> 1.0.0'
20 | gem 'mocha'
21 | end
22 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10 | * files in this directory. Styles in this file should be added after the last require_* statement.
11 | * It is generally better to create a new file per style scope.
12 | *
13 | *= require_tree .
14 | *= require_self
15 | */
16 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_with(model: example, local: true) do |form| %>
2 | <% if example.errors.any? %>
3 |
4 |
<%= pluralize(example.errors.count, "error") %> prohibited this example from being saved:
5 |
6 |
7 | <% example.errors.full_messages.each do |message| %>
8 | - <%= message %>
9 | <% end %>
10 |
11 |
12 | <% end %>
13 |
14 |
15 | <%= form.label :title %>
16 | <%= form.text_field :title, id: :example_title %>
17 |
18 |
19 |
20 | <%= form.label :comment %>
21 | <%= form.text_area :comment, id: :example_comment %>
22 |
23 |
24 |
25 | <%= form.submit %>
26 |
27 | <% end %>
28 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | begin
2 | require 'bundler/setup'
3 | rescue LoadError
4 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5 | end
6 |
7 | require 'rdoc/task'
8 |
9 | RDoc::Task.new(:rdoc) do |rdoc|
10 | rdoc.rdoc_dir = 'rdoc'
11 | rdoc.title = 'SystemTester'
12 | rdoc.options << '--line-numbers'
13 | rdoc.rdoc_files.include('README.md')
14 | rdoc.rdoc_files.include('lib/**/*.rb')
15 | end
16 |
17 | APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18 | load 'rails/tasks/engine.rake'
19 |
20 |
21 | load 'rails/tasks/statistics.rake'
22 |
23 |
24 |
25 | require 'bundler/gem_tasks'
26 |
27 | require 'rake/testtask'
28 |
29 | Rake::TestTask.new(:test) do |t|
30 | t.libs << 'test'
31 | t.pattern = 'test/**/*_test.rb'
32 | t.verbose = false
33 | end
34 |
35 |
36 | task default: :test
37 |
--------------------------------------------------------------------------------
/test/integration/system_tester/executions_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class ExecutionsControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @scenario = Fabricate(:scenario, title: "Feature Tester Title")
7 | @scenario.touch
8 | CommandHandler.any_instance.expects(:run_each_line).yields("out").returns(0)
9 | end
10 |
11 | test "#create feature" do
12 | post '/system_tester/executions', params: {feature_id: @scenario.feature.id}
13 | assert_equal 0, JSON.parse(response.body)["exit_code"]
14 | assert_response :success
15 | end
16 |
17 | test "#create scenario" do
18 | post '/system_tester/executions', params: {scenario_id: @scenario.id}
19 | assert_equal 0, JSON.parse(response.body)["exit_code"]
20 | assert_response :success
21 | end
22 |
23 | end
24 | end
--------------------------------------------------------------------------------
/app/controllers/system_tester/executions_controller.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class ExecutionsController < ApplicationController
3 | def create
4 | feature = params[:feature_id].present? ? Feature.find(params[:feature_id]) : nil
5 | scenario = params[:scenario_id].present? ? Scenario.find(params[:scenario_id]) : nil
6 | @cmd = feature.present? ? "bin/rails test #{feature.full_file}" : "bin/rails test #{scenario.feature.full_file}:#{scenario.line_number}"
7 | status = handle_command
8 | render json: {exit_code: status}
9 | end
10 |
11 | private
12 |
13 | def handle_command
14 | command_handler = CommandHandler.new(@cmd)
15 | position = 0
16 | command_handler.run_each_line do |char|
17 | ActionCable.server.broadcast "system_tester_execution", {output: char, position: position}
18 | position += 1
19 | end
20 | end
21 | end
22 | end
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | SystemTester::Engine.routes.draw do
2 | mount ActionCable.server => '/cable'
3 | resources :features, only: [:index, :create, :update, :destroy], :defaults => {:format => :json}
4 | resources :scenarios, only: [:index, :show, :create, :update, :destroy], :defaults => {:format => :json}
5 | resources :steps, only: [:index, :show, :new, :create, :update, :destroy], :defaults => {:format => :json}
6 | resources :scenario_steps, only: [:create, :update, :destroy], :defaults => {:format => :json}
7 | resources :stair_steps, only: [:create, :update, :destroy], :defaults => {:format => :json}
8 | resources :step_types, only: [:index], :defaults => {:format => :json} do
9 | collection do
10 | get :parents, :defaults => {:format => :json}
11 | end
12 | end
13 | resources :status, only: [:index], :defaults => {:format => :json}
14 | resources :executions, only: [:create]
15 | end
16 |
--------------------------------------------------------------------------------
/test/dummy/bin/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 | require 'fileutils'
4 | include FileUtils
5 |
6 | # path to your application root.
7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8 |
9 | def system!(*args)
10 | system(*args) || abort("\n== Command #{args} failed ==")
11 | end
12 |
13 | chdir APP_ROOT do
14 | # This script is a way to update your development environment automatically.
15 | # Add necessary update steps to this file.
16 |
17 | puts '== Installing dependencies =='
18 | system! 'gem install bundler --conservative'
19 | system('bundle check') || system!('bundle install')
20 |
21 | puts "\n== Updating database =="
22 | system! 'bin/rails db:migrate'
23 |
24 | puts "\n== Removing old logs and tempfiles =="
25 | system! 'bin/rails log:clear tmp:clear'
26 |
27 | puts "\n== Restarting application server =="
28 | system! 'bin/rails restart'
29 | end
30 |
--------------------------------------------------------------------------------
/app/models/system_tester/command_handler.rb:
--------------------------------------------------------------------------------
1 | require 'pty'
2 | module SystemTester
3 | class CommandHandler
4 | attr_reader :status
5 | def initialize(cmd)
6 | @cmd = cmd
7 | @status = nil
8 | end
9 |
10 | def run(&block)
11 | pty do |r,w,pid|
12 | rescue_errno pid do
13 | yield r.getc until r.eof?
14 | end
15 | end
16 | end
17 |
18 | def run_each_line(&block)
19 | pty do |r,w,pid|
20 | rescue_errno pid do
21 | r.each do |line|
22 | yield line
23 | end
24 | end
25 | end
26 | end
27 |
28 | private
29 |
30 | def pty(&block)
31 | PTY.spawn(@cmd, &block)
32 | @status = $?.exitstatus
33 | end
34 |
35 | def rescue_errno(pid, &block)
36 | begin
37 | yield
38 | rescue Errno::EIO
39 | ensure
40 | Process.wait pid
41 | end
42 | end
43 | end
44 | end
--------------------------------------------------------------------------------
/lib/system_tester/engine.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Engine < ::Rails::Engine
3 | isolate_namespace SystemTester
4 | config.generators.api_only = true
5 |
6 | initializer :cors do |app|
7 | app.config.middleware.insert_before 0, Rack::Cors do
8 | allow do
9 | origins 'ebpjncfolmfiiphibdajgblbchkklbcf', 'http://localhost:8080'
10 | resource '/system_tester/*',
11 | :headers => :any,
12 | :methods => [:get, :post, :delete, :put, :patch, :options, :head]
13 | end
14 | end
15 |
16 | app.config.action_cable.allowed_request_origins = ['chrome-extension://ebpjncfolmfiiphibdajgblbchkklbcf', 'http://localhost:8080']
17 | end
18 |
19 | config.to_prepare do
20 | if Rails.env.development?
21 | Dir.glob(SystemTester::Engine.root.join("app", "models" , "**", "*.rb")).each do |dep|
22 | require_dependency dep
23 | end
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # The following keys must be escaped otherwise they will not be retrieved by
20 | # the default I18n backend:
21 | #
22 | # true, false, on, off, yes, no
23 | #
24 | # Instead, surround them with single quotes.
25 | #
26 | # en:
27 | # 'true': 'foo'
28 | #
29 | # To learn more, please read the Rails Internationalization guide
30 | # available at http://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/system_tester.gemspec:
--------------------------------------------------------------------------------
1 | $:.push File.expand_path("../lib", __FILE__)
2 |
3 | # Maintain your gem's version:
4 | require "system_tester/version"
5 |
6 | # Describe your gem and declare its dependencies:
7 | Gem::Specification.new do |s|
8 | s.name = "system_tester"
9 | s.version = SystemTester::VERSION
10 | s.authors = ["Richard LaFranchi"]
11 | s.email = ["rlafranchi@icloud.com"]
12 | s.homepage = "http://github.com/rlafranchi/system_tester"
13 | s.summary = "System Tester: Rails Sysyem Test Management"
14 | s.description = "System Tester aims to symplify QA for Rails applications by providing a development tool for creating and managing system tests"
15 | s.license = "MIT"
16 |
17 | s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
18 |
19 | s.add_dependency "rails", "~> 5.1.0"
20 | s.add_dependency "acts_as_list", "~> 0.9.0"
21 | s.add_dependency "rack-cors"
22 |
23 | s.add_development_dependency "sqlite3"
24 | s.add_development_dependency "faker"
25 | s.add_development_dependency "fabrication"
26 | end
27 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: ruby
3 | cache: bundler
4 | rvm:
5 | - 2.3
6 | - 2.4
7 | - ruby-head
8 | before_script:
9 | - bin/rails db:migrate RAILS_ENV=test
10 | - bin/rails app:system_tester:migrate
11 | addons:
12 | code_climate:
13 | repo_token:
14 | secure: "TCYPUQZA9Cp1nZur+02JMf35tvmdKhYfmH7075KbyDNuOIUYwuaJNeea7Kzg6Oh8Ffc/1BZ6RDOPsttwJa+Hs6PFkYgFlABRPkSWuGuO8pH0oP+0f0BTi+4GOabZ2Owunb2MzGCF9wyqxuCkh40NHiXYstMId4QI60u8ac3VpC4nMHwvpbDiffOxoQf8nRs5XpVFPn9Izi9Ct9o/DgK5gnFOZKF6MEzKc6qezNnf9h3qUaa4dBHl371cjfsY4eIWeyp/UB/zt2ReamjOu4aVjZ7RJ9ckhVfbfhL7lqdW21dVRxy/ybgxeFQLS8j2HQ3hRbFvWvOsERbQ2Qxl8ni53yxJdkXRIPcBs+/Q9t3MrjcAJbZbHXlWNtaS95gsWhlDIhVigW4GDjHDkkXv5aYR9OfCrEX5pbi3bHarU11BZ6a5qGKF+bcUhRguGdfsjekc5347gda8sn88C3i7oABHn3ZTzkJVOCR1ULHsCX5l9S+81NHIoT8XRGyXmjxb7eClCX43TbvAYttJMlhM+hFagx40RHaB+kE7qIVh5jgCqLQYx2OgF2H8c/oCVoGgFS7aWHKxJ8bApI7hFL2nyLnHiRTO3KyLEXFNKaDj9RLKHNHdo2OYLhzt85WSYK6FxezjsX3XZRaZ2oCUdUSEwlQhqbpJpXkH9PjNKJktb2ogUZE="
15 | after_success:
16 | - bundle exec codeclimate-test-reporter
17 | script: bin/rails test
18 | matrix:
19 | allow_failures:
20 | - rvm: ruby-head
21 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2017 Richard LaFranchi
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/test/dummy/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 | require 'fileutils'
4 | include FileUtils
5 |
6 | # path to your application root.
7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8 |
9 | def system!(*args)
10 | system(*args) || abort("\n== Command #{args} failed ==")
11 | end
12 |
13 | chdir APP_ROOT do
14 | # This script is a starting point to setup your application.
15 | # Add necessary setup steps to this file.
16 |
17 | puts '== Installing dependencies =='
18 | system! 'gem install bundler --conservative'
19 | system('bundle check') || system!('bundle install')
20 |
21 | # Install JavaScript dependencies if using Yarn
22 | # system('bin/yarn')
23 |
24 |
25 | # puts "\n== Copying sample files =="
26 | # unless File.exist?('config/database.yml')
27 | # cp 'config/database.yml.sample', 'config/database.yml'
28 | # end
29 |
30 | puts "\n== Preparing database =="
31 | system! 'bin/rails db:setup'
32 |
33 | puts "\n== Removing old logs and tempfiles =="
34 | system! 'bin/rails log:clear tmp:clear'
35 |
36 | puts "\n== Restarting application server =="
37 | system! 'bin/rails restart'
38 | end
39 |
--------------------------------------------------------------------------------
/lib/tasks/system_tester_tasks.rake:
--------------------------------------------------------------------------------
1 | # desc "Explaining what the task does"
2 | # create install task
3 | # TODO:
4 | # - potentially load using sql instead of migrations
5 | # - auto mount in the routes
6 | # - auto add to database.yml defaulting to sqlite3
7 | # - create test directories
8 | # - copy system_tester_system_test_case
9 |
10 | # remove migration copy in favor of custom migration task
11 | Rake::Task["system_tester:install:migrations"].clear
12 | namespace :system_tester do
13 | namespace :install do
14 | desc "(Not Supported)"
15 | task "migrations" do
16 | # do nothing
17 | puts "Not supported..."
18 | end
19 | end
20 |
21 | # see ActiveRecord::Tasks::DatabaseTasks
22 | desc "Running migrations for the System Tester db"
23 | task :migrate => :environment do
24 | include ActiveRecord::Tasks
25 | ENV['RAILS_ENV'] = "system_tester"
26 | DatabaseTasks.db_dir = Rails.root.join("db")
27 | DatabaseTasks.env = "system_tester"
28 | DatabaseTasks.migrations_paths = [SystemTester::Engine.root.join("db", "migrate")]
29 | DatabaseTasks.root = Rails.root
30 | DatabaseTasks.create_current("system_tester")
31 | DatabaseTasks.migrate
32 | end
33 | end
--------------------------------------------------------------------------------
/app/controllers/system_tester/stair_steps_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class StairStepsController < ApplicationController
5 |
6 | def create
7 | stair_step = StairStep.new(stair_step_params)
8 | if stair_step.save
9 | render json: stair_step.to_json(stair_step_json_options)
10 | else
11 | render json: { errors: stair_step.errors }, status: :unprocessable_entity
12 | end
13 | end
14 |
15 | def update
16 | stair_step = StairStep.find(params[:id])
17 | if stair_step.update(stair_step_params)
18 | render json: stair_step.to_json(stair_step_json_options)
19 | else
20 | render json: { errors: stair_step.errors }, status: :unprocessable_entity
21 | end
22 | end
23 |
24 | def destroy
25 | StairStep.find(params[:id]).destroy!
26 | render json: {}
27 | end
28 |
29 | private
30 |
31 | def stair_step_params
32 | params.require(:stair_step).permit(:position, :system_tester_step_id, :system_tester_stair_id)
33 | end
34 |
35 | def stair_step_json_options
36 | {
37 | include: :step
38 | }
39 | end
40 |
41 | end
42 | end
--------------------------------------------------------------------------------
/app/models/system_tester/scenario.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Scenario < ApplicationRecord
3 | include SystemTester::TitleValidatable
4 | validates_uniqueness_of :title, scope: :system_tester_feature_id
5 |
6 | INDENT = " " * 4
7 | belongs_to :feature, class_name: "SystemTester::Feature", foreign_key: "system_tester_feature_id"
8 | has_many :scenario_steps,
9 | -> { order 'position asc' },
10 | class_name: "SystemTester::ScenarioStep",
11 | foreign_key: "system_tester_scenario_id",
12 | dependent: :destroy
13 | has_many :steps, -> { order 'position asc' }, through: :scenario_steps
14 |
15 | after_commit do
16 | feature.touch if feature.present?
17 | end
18 |
19 | def to_s
20 | str = ""
21 | str << open
22 | str << steps.map(&:to_s).join("")
23 | str << close
24 | str
25 | end
26 |
27 | def line_number
28 | lines = feature.to_s.split("\n")
29 | lines.index { |line| open.chomp === line } + 1
30 | end
31 |
32 | private
33 |
34 | def open
35 | "#{INDENT}test \"#{title}\" do\n"
36 | end
37 |
38 | def close
39 | "#{INDENT}end\n"
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/features_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class FeaturesController < ApplicationController
5 | def index
6 | render json: Feature.all.to_json(feature_json_options)
7 | end
8 |
9 | def create
10 | feature = Feature.new(feature_params)
11 | if feature.save
12 | render json: feature.to_json(feature_json_options)
13 | else
14 | render json: { errors: feature.errors }, status: :unprocessable_entity
15 | end
16 | end
17 |
18 | def update
19 | feature = Feature.find(params[:id])
20 | if feature.update(feature_params)
21 | render json: feature.to_json(feature_json_options)
22 | else
23 | render json: { errors: feature.errors }, status: :unprocessable_entity
24 | end
25 | end
26 |
27 | def destroy
28 | Feature.find(params[:id]).destroy!
29 | render json: {}
30 | end
31 |
32 | private
33 |
34 | def feature_params
35 | params.require(:feature).permit(:title)
36 | end
37 |
38 | def feature_json_options
39 | {
40 | methods: [:to_s],
41 | include: :scenarios
42 | }
43 | end
44 |
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/scenario_steps_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class ScenarioStepsController < ApplicationController
5 |
6 | def create
7 | scenario_step = ScenarioStep.new(scenario_step_params)
8 | if scenario_step.save
9 | render json: scenario_step.to_json(scenario_step_json_options)
10 | else
11 | render json: { errors: scenario_step.errors }, status: :unprocessable_entity
12 | end
13 | end
14 |
15 | def update
16 | scenario_step = ScenarioStep.find(params[:id])
17 | if scenario_step.update(scenario_step_params)
18 | render json: scenario_step.to_json(scenario_step_json_options)
19 | else
20 | render json: { errors: scenario_step.errors }, status: :unprocessable_entity
21 | end
22 | end
23 |
24 | def destroy
25 | ScenarioStep.find(params[:id]).destroy!
26 | render json: {}
27 | end
28 |
29 | private
30 |
31 | def scenario_step_params
32 | params.require(:scenario_step).permit(:position, :system_tester_step_id, :system_tester_scenario_id)
33 | end
34 |
35 | def scenario_step_json_options
36 | {
37 | include: :step
38 | }
39 | end
40 |
41 | end
42 | end
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/scaffold.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #fff;
3 | color: #333;
4 | margin: 33px;
5 | }
6 |
7 | body, p, ol, ul, td {
8 | font-family: verdana, arial, helvetica, sans-serif;
9 | font-size: 13px;
10 | line-height: 18px;
11 | }
12 |
13 | pre {
14 | background-color: #eee;
15 | padding: 10px;
16 | font-size: 11px;
17 | }
18 |
19 | a {
20 | color: #000;
21 | }
22 |
23 | a:visited {
24 | color: #666;
25 | }
26 |
27 | a:hover {
28 | color: #fff;
29 | background-color: #000;
30 | }
31 |
32 | th {
33 | padding-bottom: 5px;
34 | }
35 |
36 | td {
37 | padding: 0 5px 7px;
38 | }
39 |
40 | div.field,
41 | div.actions {
42 | margin-bottom: 10px;
43 | }
44 |
45 | #notice {
46 | color: green;
47 | }
48 |
49 | .field_with_errors {
50 | padding: 2px;
51 | background-color: red;
52 | display: table;
53 | }
54 |
55 | #error_explanation {
56 | width: 450px;
57 | border: 2px solid red;
58 | padding: 7px 7px 0;
59 | margin-bottom: 20px;
60 | background-color: #f0f0f0;
61 | }
62 |
63 | #error_explanation h2 {
64 | text-align: left;
65 | font-weight: bold;
66 | padding: 5px 5px 5px 15px;
67 | font-size: 12px;
68 | margin: -7px -7px 0;
69 | background-color: #c00;
70 | color: #fff;
71 | }
72 |
73 | #error_explanation ul li {
74 | font-size: 12px;
75 | list-style: square;
76 | }
77 |
78 | label {
79 | display: block;
80 | }
81 |
--------------------------------------------------------------------------------
/app/models/system_tester/visit.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Visit < Action
3 | @@engines = {}
4 |
5 | def to_s
6 | "#{super}#{INDENT}visit \"#{arg_one}\"\n\n"
7 | end
8 |
9 | def self.args
10 | [
11 | {
12 | name: "arg_one",
13 | label: "Path or Url",
14 | type: "autocomplete",
15 | options: collect_routes(Rails.application.routes.routes)
16 | }
17 | ]
18 | end
19 |
20 | private
21 |
22 | # Snatched from action_dispatch/routing/inspector
23 | def self.collect_routes(routes)
24 | routes.collect do |route|
25 | ActionDispatch::Routing::RouteWrapper.new(route)
26 | end.reject do |route|
27 | route.internal? || route.reqs.starts_with?("system_tester", "SystemTester") || route.verb != "GET"
28 | end.collect do |route|
29 | collect_engine_routes(route)
30 | {
31 | name: "#{route.name}_path",
32 | value: route.path
33 | }
34 | end.concat(@@engines.values)
35 | end
36 |
37 | def self.collect_engine_routes(route)
38 | name = route.endpoint
39 | return unless route.engine?
40 | return if @@engines[name]
41 |
42 | routes = route.rack_app.routes
43 | if routes.is_a?(ActionDispatch::Routing::RouteSet)
44 | @@engines[name] = collect_routes(routes.routes)
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/test/dummy/config/secrets.yml:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rails secret` to generate a secure secret key.
9 |
10 | # Make sure the secrets in this file are kept private
11 | # if you're sharing your code publicly.
12 |
13 | # Shared secrets are available across all environments.
14 |
15 | # shared:
16 | # api_key: a1B2c3D4e5F6
17 |
18 | # Environmental secrets are only available for that specific environment.
19 |
20 | development:
21 | secret_key_base: 18a018785429ff51a471552fb17eece138e9422dca71868a5a512616e05a8e9728760b39fa2b1e3f8e269057cf215f5c5e3adfc73f0bffcfeceb80a4c753bafd
22 |
23 | test:
24 | secret_key_base: 4849af7e2ba9212bf8793b8eb85d34365c595cab2834a499aa7b1ff7f178b64e66ba0ce0138cddfc1757c88ff78fe862decc530ec3d6e46f64071fd7d0bc4216
25 |
26 | # Do not keep production secrets in the unencrypted secrets file.
27 | # Instead, either read values from the environment.
28 | # Or, use `bin/rails secrets:setup` to configure encrypted secrets
29 | # and move the `production:` environment over there.
30 |
31 | production:
32 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
33 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/examples_controller.rb:
--------------------------------------------------------------------------------
1 | class ExamplesController < ApplicationController
2 | before_action :set_example, only: [:show, :edit, :update, :destroy]
3 |
4 | # GET /examples
5 | def index
6 | @examples = Example.all
7 | end
8 |
9 | # GET /examples/1
10 | def show
11 | end
12 |
13 | # GET /examples/new
14 | def new
15 | @example = Example.new
16 | end
17 |
18 | # GET /examples/1/edit
19 | def edit
20 | end
21 |
22 | # POST /examples
23 | def create
24 | @example = Example.new(example_params)
25 |
26 | if @example.save
27 | redirect_to @example, notice: 'Example was successfully created.'
28 | else
29 | render :new
30 | end
31 | end
32 |
33 | # PATCH/PUT /examples/1
34 | def update
35 | if @example.update(example_params)
36 | redirect_to @example, notice: 'Example was successfully updated.'
37 | else
38 | render :edit
39 | end
40 | end
41 |
42 | # DELETE /examples/1
43 | def destroy
44 | @example.destroy
45 | redirect_to examples_url, notice: 'Example was successfully destroyed.'
46 | end
47 |
48 | private
49 | # Use callbacks to share common setup or constraints between actions.
50 | def set_example
51 | @example = Example.find(params[:id])
52 | end
53 |
54 | # Only allow a trusted parameter "white list" through.
55 | def example_params
56 | params.require(:example).permit(:title, :comment)
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/scenarios_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class ScenariosController < ApplicationController
5 | def index
6 | render json: Scenario.all.to_json(scenario_json_options)
7 | end
8 |
9 | def show
10 | scenario = Scenario.find(params[:id])
11 | render json: scenario.to_json(scenario_json_options)
12 | end
13 |
14 | def create
15 | scenario = Scenario.new(scenario_params)
16 | if scenario.save
17 | render json: scenario.to_json(scenario_json_options)
18 | else
19 | render json: { errors: scenario.errors }, status: :unprocessable_entity
20 | end
21 | end
22 |
23 | def update
24 | scenario = Scenario.find(params[:id])
25 | if scenario.update(scenario_params)
26 | render json: scenario.to_json(scenario_json_options)
27 | else
28 | render json: { errors: scenario.errors }, status: :unprocessable_entity
29 | end
30 | end
31 |
32 | def destroy
33 | Scenario.find(params[:id]).destroy!
34 | render json: {}
35 | end
36 |
37 | private
38 |
39 | def scenario_params
40 | params.require(:scenario).permit(:title, :system_tester_feature_id)
41 | end
42 |
43 | def scenario_json_options
44 | {
45 | include: {
46 | scenario_steps: {
47 | include: {
48 | step: {
49 | methods: [:friendly_type, :parent_type, :bg_css, :text_css, :icon]
50 | }
51 | }
52 | },
53 | feature: {}
54 | },
55 | methods: [:to_s]
56 | }
57 | end
58 |
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/app/models/system_tester/feature.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Feature < ApplicationRecord
3 | include SystemTester::TitleValidatable
4 | include SystemTester::Fileable
5 | validates_uniqueness_of :title
6 |
7 | has_many :scenarios, foreign_key: "system_tester_feature_id", class_name: 'SystemTester::Scenario', dependent: :destroy
8 |
9 | def to_s
10 | str = ""
11 | str << open
12 | str << scenarios.map(&:to_s).join("")
13 | str << close
14 | str
15 | end
16 | alias_method :code_to_write, :to_s
17 |
18 | private
19 |
20 | def open
21 | str = ""
22 | stairs.each do |stair|
23 | str << "require 'support/system_tester/#{stair.method_name}'\n"
24 | end
25 | str << "require_relative 'system_tester_system_test_case'\n\n"
26 | str << "module SystemTester\n"
27 | str << " class #{stripped_title.camelize}Test < SystemTesterSystemTestCase\n"
28 | stairs.each do |stair|
29 | str << " include #{stair.module_name}\n"
30 | end
31 | str << "\n" unless stairs.empty?
32 | str
33 | end
34 |
35 | def close
36 | " end\nend\n"
37 | end
38 |
39 | def stripped_title
40 | title.gsub(/\s+/,"")
41 | end
42 |
43 | def stripped_title_was
44 | title_was.gsub(/\s+/,"")
45 | end
46 |
47 | def stairs
48 | Stair.joins(:scenarios).where("system_tester_scenarios.system_tester_feature_id = ?", id)
49 | end
50 |
51 | def base_dir
52 | File.join("system", "system_tester")
53 | end
54 |
55 | def file_name
56 | "#{stripped_title.underscore}_test.rb"
57 | end
58 |
59 | def file_name_was
60 | "#{stripped_title_was.underscore}_test.rb"
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/app/controllers/system_tester/steps_controller.rb:
--------------------------------------------------------------------------------
1 | require_dependency "system_tester/application_controller"
2 |
3 | module SystemTester
4 | class StepsController < ApplicationController
5 | def index
6 | render json: Step.all.to_json(step_json_options)
7 | end
8 |
9 | def show
10 | render json: Step.find(params[:id]).to_json(step_json_options)
11 | end
12 |
13 | def new
14 | render json: Step.new(step_params).to_json(step_json_options)
15 | end
16 |
17 | def create
18 | step = Step.new(step_params)
19 | if step.save
20 | render json: step.to_json(step_json_options)
21 | else
22 | render json: { errors: step.errors }, status: :unprocessable_entity
23 | end
24 | end
25 |
26 | def update
27 | step = Step.find(params[:id])
28 | if step.update(step_params)
29 | render json: step.to_json(step_json_options)
30 | else
31 | render json: { errors: step.errors }, status: :unprocessable_entity
32 | end
33 | end
34 |
35 | def destroy
36 | Step.find(params[:id]).destroy!
37 | render json: {}
38 | end
39 |
40 | private
41 |
42 | def step_params
43 | params.require(:step).permit(:title, :type, :arg_one, :arg_two)
44 | end
45 |
46 | def step_json_options
47 | {
48 | methods: [:type, :friendly_type, :parent_type, :to_s, :bg_css, :text_css, :icon, :module],
49 | include: {
50 | scenarios: {},
51 | stair_steps: {
52 | include: {
53 | step: {
54 | methods: [:friendly_type, :parent_type, :bg_css, :text_css, :icon]
55 | }
56 | }
57 | }
58 | }
59 | }
60 | end
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/app/models/system_tester/stair.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Stair < Step
3 | include SystemTester::TitleValidatable
4 | validates_uniqueness_of :title
5 | include SystemTester::Fileable
6 | has_many :stair_steps,
7 | -> { order 'position asc' },
8 | class_name: "SystemTester::StairStep",
9 | foreign_key: "system_tester_stair_id",
10 | dependent: :destroy
11 | has_many :steps, -> { order 'position asc' }, through: :stair_steps
12 |
13 | def to_s
14 | "#{INDENT}# Stair: #{title}\n#{INDENT}#{method_name}\n\n"
15 | end
16 |
17 | def module
18 | str = ""
19 | str << open
20 | str << steps.map(&:to_s).join("")
21 | str << close
22 | str
23 | end
24 | alias_method :code_to_write, :module
25 |
26 | def module_name
27 | stripped_title.camelize
28 | end
29 |
30 | def method_name
31 | stripped_title.underscore
32 | end
33 |
34 | def icon
35 | "clear_all"
36 | end
37 |
38 | def self.bg_css
39 | "deep-purple"
40 | end
41 |
42 | private
43 |
44 | def open
45 | str = ""
46 | str << "module SystemTester\n"
47 | str << " module #{module_name}\n"
48 | str << " def #{method_name}\n"
49 | str
50 | end
51 |
52 | def close
53 | " end\n end\nend\n"
54 | end
55 |
56 | def stripped_title
57 | title.gsub(/\s+/,"")
58 | end
59 |
60 | def stripped_title_was
61 | title_was.gsub(/\s+/,"")
62 | end
63 |
64 | def method_name_was
65 | stripped_title_was.underscore
66 | end
67 |
68 | def base_dir
69 | File.join("support", "system_tester")
70 | end
71 |
72 | def file_name
73 | "#{method_name}.rb"
74 | end
75 |
76 | def file_name_was
77 | "#{method_name_was}.rb"
78 | end
79 | end
80 | end
--------------------------------------------------------------------------------
/test/dummy/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
2 | ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../test/dummy/db/migrate", __FILE__)]
3 | ActiveRecord::Migrator.migrations_paths << File.expand_path('../../db/migrate', __FILE__)
4 | require "rails/test_help"
5 | require "mocha/mini_test"
6 | require "faker"
7 | require "fabrication"
8 | require "simplecov"
9 | SimpleCov.start :rails do
10 | filters.clear
11 | add_filter do |src|
12 | !(src.filename =~ /^#{SimpleCov.root}/) unless src.filename =~ /system_tester/
13 | end
14 | add_filter '/app/jobs/'
15 | add_filter '/lib/'
16 | add_filter '/test/'
17 | end
18 |
19 | Fabrication.configure do |config|
20 | config.fabricator_path = 'test/fabricators'
21 | config.path_prefix = SystemTester::Engine.root
22 | end
23 |
24 | class ActionDispatch::IntegrationTest
25 |
26 | # Drop all columns after each test case.
27 | teardown :clean_up
28 | def clean_up
29 | SystemTester::Feature.destroy_all
30 | SystemTester::Stair.destroy_all
31 | path1 = Rails.root.join("test", "system", "system_tester")
32 | path2 = Rails.root.join("test", "support", "system_tester")
33 | FileUtils.rm_r(path1) if File.exist?(path1)
34 | FileUtils.rm_r(path2) if File.exist?(path2)
35 | end
36 |
37 | end
38 |
39 | # Filter out Minitest backtrace while allowing backtrace from other libraries
40 | # to be shown.
41 | Minitest.backtrace_filter = Minitest::BacktraceFilter.new
42 |
43 |
44 | # Load fixtures from the engine
45 | # if ActiveSupport::TestCase.respond_to?(:fixture_path=)
46 | # ActiveSupport::TestCase.fixture_path = File.expand_path("./fabricators/system_tester", __FILE__)
47 | # ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
48 | # ActiveSupport::TestCase.file_fixture_path = File.expand_path("./fixtures/files", __FILE__)
49 | # # ActiveSupport::TestCase.fixtures :all
50 | # end
51 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure public file server for tests with Cache-Control for performance.
16 | config.public_file_server.enabled = false
17 | # config.public_file_server.headers = {
18 | # 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}"
19 | # }
20 |
21 | # Show full error reports and disable caching.
22 | config.consider_all_requests_local = true
23 | config.action_controller.perform_caching = false
24 |
25 | # Raise exceptions instead of rendering exception templates.
26 | config.action_dispatch.show_exceptions = false
27 |
28 | # Disable request forgery protection in test environment.
29 | config.action_controller.allow_forgery_protection = false
30 | config.action_mailer.perform_caching = false
31 |
32 | # Tell Action Mailer not to deliver emails to the real world.
33 | # The :test delivery method accumulates sent emails in the
34 | # ActionMailer::Base.deliveries array.
35 | config.action_mailer.delivery_method = :test
36 |
37 | # Print deprecation notices to the stderr.
38 | config.active_support.deprecation = :stderr
39 |
40 | # Raises error for missing translations
41 | # config.action_view.raise_on_missing_translations = true
42 | end
43 |
--------------------------------------------------------------------------------
/app/models/concerns/system_tester/fileable.rb:
--------------------------------------------------------------------------------
1 | require 'fileutils'
2 |
3 | module SystemTester
4 | module Fileable
5 | extend ActiveSupport::Concern
6 |
7 | included do
8 | before_save do
9 | FileUtils.mkdir_p(base_path)
10 | unless File.exists?(system_test_case_path) || "support".match(system_test_case_path)
11 | File.open(system_test_case_path, "w+") { |f| f.write(system_test_case_content) }
12 | end
13 | end
14 |
15 | after_touch do
16 | save_file
17 | end
18 |
19 | before_create do
20 | save_file
21 | end
22 |
23 | before_update do
24 | if title_changed?
25 | delete_old_file
26 | end
27 | save_file
28 | end
29 |
30 | before_destroy do
31 | delete_file
32 | end
33 |
34 | def full_file
35 | File.join(base_path, file_name)
36 | end
37 |
38 | private
39 |
40 | def test_path
41 | Rails.root.join("test")
42 | end
43 |
44 | def base_path
45 | File.join(test_path, base_dir)
46 | end
47 |
48 | def old_file
49 | File.join(base_path, file_name_was)
50 | end
51 |
52 | def delete_file
53 | File.delete(full_file) if File.exist?(full_file)
54 | end
55 |
56 | def delete_old_file
57 | File.delete(old_file)
58 | end
59 |
60 | def save_file
61 | File.open(full_file, 'w+') do |f|
62 | f.write(code_to_write)
63 | end
64 | end
65 |
66 | def system_test_case_path
67 | File.join(base_path, "system_tester_system_test_case.rb")
68 | end
69 |
70 | def system_test_case_content
71 | <
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/test/dummy/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/test/integration/system_tester/stair_steps_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class StairStepsControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @stair_step = Fabricate(:stair_step)
7 | @stair_step.touch
8 | end
9 |
10 | test "#create" do
11 | assert_difference 'SystemTester::StairStep.count', 1 do
12 | post '/system_tester/stair_steps', params: stair_step_params
13 | end
14 | assert_response :success
15 | end
16 |
17 | test "#create invalid" do
18 | post '/system_tester/stair_steps', params: stair_step_params(nil, -1, -1)
19 | assert JSON.parse(response.body)["errors"]["step"].present?
20 | assert JSON.parse(response.body)["errors"]["stair"].present?
21 | assert_response :unprocessable_entity
22 | end
23 |
24 | test "#update" do
25 | Fabricate(:stair_step, position: 2, step: @stair_step.step, stair: @stair_step.stair)
26 | put stair_step_path, params: stair_step_params(2)
27 | assert_equal 2, @stair_step.reload.position
28 | assert_response :success
29 | end
30 |
31 | test "#update invalid" do
32 | put stair_step_path, params: stair_step_params(nil,-1, -1)
33 | assert JSON.parse(response.body)["errors"]["step"].present?
34 | assert JSON.parse(response.body)["errors"]["stair"].present?
35 | assert_response :unprocessable_entity
36 | end
37 |
38 | test "#destroy" do
39 | assert_difference 'SystemTester::StairStep.count', -1 do
40 | delete stair_step_path
41 | end
42 | assert_response :success
43 | end
44 |
45 | private
46 |
47 | def stair_step_path
48 | "/system_tester/stair_steps/#{@stair_step.id}"
49 | end
50 |
51 | def stair_step_params(position=nil, step_id=nil, stair_id=nil)
52 | {
53 | stair_step: {
54 | position: position || 1,
55 | system_tester_step_id: step_id || @stair_step.step.id,
56 | system_tester_stair_id: stair_id || @stair_step.stair.id
57 | }
58 | }
59 | end
60 | end
61 | end
--------------------------------------------------------------------------------
/test/dummy/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports.
13 | config.consider_all_requests_local = true
14 |
15 | # Enable/disable caching. By default caching is disabled.
16 | if Rails.root.join('tmp/caching-dev.txt').exist?
17 | config.action_controller.perform_caching = true
18 |
19 | config.cache_store = :memory_store
20 | config.public_file_server.headers = {
21 | 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
22 | }
23 | else
24 | config.action_controller.perform_caching = false
25 |
26 | config.cache_store = :null_store
27 | end
28 |
29 | # Don't care if the mailer can't send.
30 | config.action_mailer.raise_delivery_errors = false
31 |
32 | config.action_mailer.perform_caching = false
33 |
34 | # Print deprecation notices to the Rails logger.
35 | config.active_support.deprecation = :log
36 |
37 | # Raise an error on page load if there are pending migrations.
38 | config.active_record.migration_error = :page_load
39 |
40 | # Debug mode disables concatenation and preprocessing of assets.
41 | # This option may cause significant delays in view rendering with a large
42 | # number of complex assets.
43 | config.assets.debug = true
44 |
45 | # Suppress logger output for asset requests.
46 | config.assets.quiet = true
47 |
48 | # Raises error for missing translations
49 | # config.action_view.raise_on_missing_translations = true
50 |
51 | # Use an evented file watcher to asynchronously detect changes in source code,
52 | # routes, locales, etc. This feature depends on the listen gem.
53 | # config.file_watcher = ActiveSupport::EventedFileUpdateChecker
54 | end
55 |
--------------------------------------------------------------------------------
/test/integration/system_tester/features_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class FeaturesControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @feature = Fabricate(:feature, title: "Feature Tester Title")
7 | @feature.touch
8 | end
9 |
10 | test "#index" do
11 | get '/system_tester/features'
12 | feature_from_response = get_feature(JSON.parse(response.body))
13 | assert_match "FeatureTesterTitle", feature_from_response["to_s"]
14 | assert_response :success
15 | end
16 |
17 | test "#create" do
18 | assert_difference 'SystemTester::Feature.count', 1 do
19 | post '/system_tester/features', params: feature_params
20 | end
21 | assert_response :success
22 | end
23 |
24 | test "#create invalid" do
25 | post '/system_tester/features', params: feature_params(@feature.title)
26 | assert JSON.parse(response.body)["errors"]["title"].present?
27 | assert_response :unprocessable_entity
28 | end
29 |
30 | test "#update" do
31 | new_title = "New Feature Title"
32 | put feature_path, params: feature_params(new_title)
33 | assert File.exist?(Rails.root.join("test", "system", "system_tester", "new_feature_title_test.rb"))
34 | assert_equal new_title, @feature.reload.title
35 | assert_response :success
36 | end
37 |
38 | test "#update invalid" do
39 | other_feature = Fabricate(:feature, title: "Other Feature Title")
40 | put feature_path, params: feature_params(other_feature.title)
41 | assert JSON.parse(response.body)["errors"]["title"].present?
42 | assert_response :unprocessable_entity
43 | end
44 |
45 | test "#destroy" do
46 | assert_difference 'SystemTester::Feature.count', -1 do
47 | delete feature_path
48 | end
49 | assert_response :success
50 | end
51 |
52 | private
53 |
54 | def feature_path
55 | "/system_tester/features/#{@feature.id}"
56 | end
57 |
58 | def feature_params(title=Faker::Lorem.words(2).join(" "))
59 | {
60 | feature: {
61 | title: title
62 | }
63 | }
64 | end
65 |
66 | def get_feature(response)
67 | response.select { |f| f["id"] == @feature.id }.first
68 | end
69 | end
70 | end
--------------------------------------------------------------------------------
/test/integration/system_tester/scenario_steps_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class ScenarioStepsControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @scenario_step = Fabricate(:scenario_step)
7 | @scenario_step.touch
8 | end
9 |
10 | test "#create" do
11 | assert_difference 'SystemTester::ScenarioStep.count', 1 do
12 | post '/system_tester/scenario_steps', params: scenario_step_params
13 | end
14 | assert_response :success
15 | end
16 |
17 | test "#create invalid" do
18 | post '/system_tester/scenario_steps', params: scenario_step_params(nil, -1, -1)
19 | assert JSON.parse(response.body)["errors"]["step"].present?
20 | assert JSON.parse(response.body)["errors"]["scenario"].present?
21 | assert_response :unprocessable_entity
22 | end
23 |
24 | test "#create for stair" do
25 | stair = Fabricate(:stair)
26 | assert_difference 'SystemTester::ScenarioStep.count', 1 do
27 | post '/system_tester/scenario_steps', params: scenario_step_params(nil, stair.id)
28 | end
29 | assert_response :success
30 | end
31 |
32 | test "#update" do
33 | Fabricate(:scenario_step, position: 2, step: @scenario_step.step, scenario: @scenario_step.scenario)
34 | put scenario_step_path, params: scenario_step_params(2)
35 | assert_equal 2, @scenario_step.reload.position
36 | assert_response :success
37 | end
38 |
39 | test "#update invalid" do
40 | put scenario_step_path, params: scenario_step_params(nil,-1, -1)
41 | assert JSON.parse(response.body)["errors"]["step"].present?
42 | assert JSON.parse(response.body)["errors"]["scenario"].present?
43 | assert_response :unprocessable_entity
44 | end
45 |
46 | test "#destroy" do
47 | assert_difference 'SystemTester::ScenarioStep.count', -1 do
48 | delete scenario_step_path
49 | end
50 | assert_response :success
51 | end
52 |
53 | private
54 |
55 | def scenario_step_path
56 | "/system_tester/scenario_steps/#{@scenario_step.id}"
57 | end
58 |
59 | def scenario_step_params(position=nil, step_id=nil, scenario_id=nil)
60 | {
61 | scenario_step: {
62 | position: position || 1,
63 | system_tester_step_id: step_id || @scenario_step.step.id,
64 | system_tester_scenario_id: scenario_id || @scenario_step.scenario.id
65 | }
66 | }
67 | end
68 | end
69 | end
--------------------------------------------------------------------------------
/test/integration/system_tester/scenarios_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class ScenariosControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @scenario = Fabricate(:scenario)
7 | @scenario.touch
8 | end
9 |
10 | test "#index" do
11 | get '/system_tester/scenarios'
12 | scenario_from_response = get_scenario(JSON.parse(response.body))
13 | assert_match @scenario.title, scenario_from_response["to_s"]
14 | assert_response :success
15 | end
16 |
17 | test "#show" do
18 | get scenario_path
19 | assert_response :success
20 | end
21 |
22 | test "#create" do
23 | assert_difference 'SystemTester::Scenario.count', 1 do
24 | post '/system_tester/scenarios', params: scenario_params
25 | end
26 | assert_response :success
27 | end
28 |
29 | test "#create invalid" do
30 | post '/system_tester/scenarios', params: scenario_params(@scenario.title, @scenario.system_tester_feature_id)
31 | assert JSON.parse(response.body)["errors"]["title"].present?
32 | assert_response :unprocessable_entity
33 | end
34 |
35 | test "#update" do
36 | new_title = Faker::Lorem.words(2).join(" ")
37 | put scenario_path, params: scenario_params(new_title)
38 | assert_equal new_title, @scenario.reload.title
39 | assert_response :success
40 | end
41 |
42 | test "#update invalid" do
43 | other_scenario = Fabricate(:scenario, title: "Other scenario Title")
44 | put scenario_path, params: scenario_params(other_scenario.title, other_scenario.system_tester_feature_id)
45 | assert JSON.parse(response.body)["errors"]["title"].present?
46 | assert_response :unprocessable_entity
47 | end
48 |
49 | test "#destroy" do
50 | assert_difference 'SystemTester::Scenario.count', -1 do
51 | delete scenario_path
52 | end
53 | assert_response :success
54 | end
55 |
56 | private
57 |
58 | def scenario_path
59 | "/system_tester/scenarios/#{@scenario.id}"
60 | end
61 |
62 | def scenario_params(title=nil, feature_id=nil)
63 | title = title || Faker::Lorem.words(2).join(" ")
64 | {
65 | scenario: {
66 | title: title,
67 | system_tester_feature_id: feature_id || Fabricate(:feature).id
68 | }
69 | }
70 | end
71 |
72 | def get_scenario(response)
73 | response.select { |f| f["id"] == @scenario.id }.first
74 | end
75 | end
76 | end
--------------------------------------------------------------------------------
/test/dummy/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8 | threads threads_count, threads_count
9 |
10 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
11 | #
12 | port ENV.fetch("PORT") { 3000 }
13 |
14 | # Specifies the `environment` that Puma will run in.
15 | #
16 | environment ENV.fetch("RAILS_ENV") { "development" }
17 |
18 | # Specifies the number of `workers` to boot in clustered mode.
19 | # Workers are forked webserver processes. If using threads and workers together
20 | # the concurrency of the application would be max `threads` * `workers`.
21 | # Workers do not work on JRuby or Windows (both of which do not support
22 | # processes).
23 | #
24 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
25 |
26 | # Use the `preload_app!` method when specifying a `workers` number.
27 | # This directive tells Puma to first boot the application and load code
28 | # before forking the application. This takes advantage of Copy On Write
29 | # process behavior so workers use less memory. If you use this option
30 | # you need to make sure to reconnect any threads in the `on_worker_boot`
31 | # block.
32 | #
33 | # preload_app!
34 |
35 | # If you are preloading your application and using Active Record, it's
36 | # recommended that you close any connections to the database before workers
37 | # are forked to prevent connection leakage.
38 | #
39 | # before_fork do
40 | # ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
41 | # end
42 |
43 | # The code in the `on_worker_boot` will be called if you are using
44 | # clustered mode by specifying a number of `workers`. After each worker
45 | # process is booted, this block will be run. If you are using the `preload_app!`
46 | # option, you will want to use this block to reconnect to any threads
47 | # or connections that may have been created at application boot, as Ruby
48 | # cannot share connections between processes.
49 | #
50 | # on_worker_boot do
51 | # ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
52 | # end
53 | #
54 |
55 | # Allow puma to be restarted by `rails restart` command.
56 | plugin :tmp_restart
57 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # Note that this schema.rb definition is the authoritative source for your
6 | # database schema. If you need to create the application database on another
7 | # system, you should be using db:schema:load, not running all the migrations
8 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 | # you'll amass, the slower it'll run and the greater likelihood for issues).
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 20170629120850) do
14 |
15 | create_table "system_tester_features", force: :cascade do |t|
16 | t.string "title"
17 | t.datetime "created_at", null: false
18 | t.datetime "updated_at", null: false
19 | end
20 |
21 | create_table "system_tester_scenario_steps", force: :cascade do |t|
22 | t.integer "position"
23 | t.integer "system_tester_step_id"
24 | t.integer "system_tester_scenario_id"
25 | t.datetime "created_at", null: false
26 | t.datetime "updated_at", null: false
27 | t.index ["system_tester_scenario_id"], name: "index_st_st_scenario_id"
28 | t.index ["system_tester_step_id"], name: "index_system_tester_scenario_steps_on_system_tester_step_id"
29 | end
30 |
31 | create_table "system_tester_scenarios", force: :cascade do |t|
32 | t.string "title"
33 | t.integer "system_tester_feature_id"
34 | t.datetime "created_at", null: false
35 | t.datetime "updated_at", null: false
36 | t.index ["system_tester_feature_id"], name: "index_system_tester_scenarios_on_system_tester_feature_id"
37 | end
38 |
39 | create_table "system_tester_stair_steps", force: :cascade do |t|
40 | t.integer "position"
41 | t.integer "system_tester_step_id"
42 | t.integer "system_tester_stair_id"
43 | t.datetime "created_at", null: false
44 | t.datetime "updated_at", null: false
45 | t.index ["system_tester_stair_id"], name: "index_system_tester_stair_steps_on_system_tester_stair_id"
46 | t.index ["system_tester_step_id"], name: "index_system_tester_stair_steps_on_system_tester_step_id"
47 | end
48 |
49 | create_table "system_tester_steps", force: :cascade do |t|
50 | t.string "title"
51 | t.string "type"
52 | t.string "arg_one"
53 | t.string "arg_two"
54 | t.datetime "created_at", null: false
55 | t.datetime "updated_at", null: false
56 | end
57 |
58 | end
59 |
--------------------------------------------------------------------------------
/app/models/system_tester/step.rb:
--------------------------------------------------------------------------------
1 | module SystemTester
2 | class Step < ApplicationRecord
3 | # include TitleValidatable
4 | validates_presence_of :title
5 | validates_uniqueness_of :title, scope: [:type, :arg_one, :arg_two]
6 |
7 | INDENT = " " * 6
8 | has_many :scenario_steps,
9 | class_name: "SystemTester::ScenarioStep",
10 | foreign_key: "system_tester_step_id",
11 | dependent: :destroy
12 | has_many :scenarios, through: :scenario_steps
13 |
14 | has_many :stair_steps,
15 | class_name: "SystemTester::StairStep",
16 | foreign_key: "system_tester_step_id",
17 | dependent: :destroy
18 | has_many :stairs, through: :stair_steps
19 |
20 | after_commit do
21 | stairs.each do |stair|
22 | stair.touch
23 | end
24 | scenarios.each do |scenario|
25 | scenario.feature.touch if scenario.feature.present?
26 | end
27 | end
28 |
29 | def self.friendly_type
30 | name.demodulize
31 | end
32 |
33 | def self.parent_type
34 | ancestors.fourth.name ? ancestors.fourth.name.demodulize : "Step"
35 | end
36 |
37 | def self.bg_css
38 | "teal"
39 | end
40 |
41 | def self.text_css
42 | "white-text"
43 | end
44 |
45 | def friendly_type
46 | self.class.friendly_type
47 | end
48 |
49 | def parent_type
50 | self.class.parent_type
51 | end
52 |
53 | def bg_css
54 | self.class.bg_css
55 | end
56 |
57 | def text_css
58 | self.class.text_css
59 | end
60 |
61 | def module
62 | ""
63 | end
64 |
65 | def self.args
66 | [
67 | {
68 | name: 'arg_one',
69 | label: 'One',
70 | type: 'text'
71 | },
72 | {
73 | name: 'arg_two',
74 | label: 'Two',
75 | type: 'text'
76 | }
77 | ]
78 | end
79 |
80 | def self.leafs
81 | (descendants - direct_descendants).map do |desc|
82 | {
83 | name: desc.to_s,
84 | friendly: desc.friendly_type,
85 | parent: desc.parent_type,
86 | args: desc.args
87 | }
88 | end.sort_by { |step_type| [step_type[:parent_type], step_type[:friendly]] }
89 | end
90 |
91 | def self.parent_types
92 | direct_descendants.map do |desc|
93 | {
94 | name: desc.to_s,
95 | friendly: desc.friendly_type
96 | }
97 | end.sort_by { |step_type| step_type[:friendly] }
98 | end
99 |
100 | def commented_title
101 | title.split("\n").map { |line| "# #{line}" }.join("\n")[2..-1]
102 | end
103 | end
104 | end
105 |
--------------------------------------------------------------------------------
/test/dummy/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # Note that this schema.rb definition is the authoritative source for your
6 | # database schema. If you need to create the application database on another
7 | # system, you should be using db:schema:load, not running all the migrations
8 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 | # you'll amass, the slower it'll run and the greater likelihood for issues).
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 20170629120850) do
14 |
15 | create_table "examples", force: :cascade do |t|
16 | t.string "title"
17 | t.text "comment"
18 | t.datetime "created_at", null: false
19 | t.datetime "updated_at", null: false
20 | end
21 |
22 | create_table "system_tester_features", force: :cascade do |t|
23 | t.string "title"
24 | t.datetime "created_at", null: false
25 | t.datetime "updated_at", null: false
26 | end
27 |
28 | create_table "system_tester_scenario_steps", force: :cascade do |t|
29 | t.integer "position"
30 | t.integer "system_tester_step_id"
31 | t.integer "system_tester_scenario_id"
32 | t.datetime "created_at", null: false
33 | t.datetime "updated_at", null: false
34 | t.index ["system_tester_scenario_id"], name: "index_st_st_scenario_id"
35 | t.index ["system_tester_step_id"], name: "index_system_tester_scenario_steps_on_system_tester_step_id"
36 | end
37 |
38 | create_table "system_tester_scenarios", force: :cascade do |t|
39 | t.string "title"
40 | t.integer "system_tester_feature_id"
41 | t.datetime "created_at", null: false
42 | t.datetime "updated_at", null: false
43 | t.index ["system_tester_feature_id"], name: "index_system_tester_scenarios_on_system_tester_feature_id"
44 | end
45 |
46 | create_table "system_tester_stair_steps", force: :cascade do |t|
47 | t.integer "position"
48 | t.integer "system_tester_step_id"
49 | t.integer "system_tester_stair_id"
50 | t.datetime "created_at", null: false
51 | t.datetime "updated_at", null: false
52 | t.index ["system_tester_stair_id"], name: "index_system_tester_stair_steps_on_system_tester_stair_id"
53 | t.index ["system_tester_step_id"], name: "index_system_tester_stair_steps_on_system_tester_step_id"
54 | end
55 |
56 | create_table "system_tester_steps", force: :cascade do |t|
57 | t.string "title"
58 | t.string "type"
59 | t.string "arg_one"
60 | t.string "arg_two"
61 | t.datetime "created_at", null: false
62 | t.datetime "updated_at", null: false
63 | end
64 |
65 | end
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/rlafranchi/system_tester)
2 | [](https://codeclimate.com/github/rlafranchi/system_tester)
3 | [](https://codeclimate.com/github/rlafranchi/system_tester/coverage)
4 | # System Tester
5 | A development tool for creating and managing system tests in Ruby on Rails >= 5.1 applications
6 |
7 | ## Usage
8 | This gem is used only in development and is a mountable rails engine that creates JSON endpoints for a chrome extension.
9 |
10 | ## Installation
11 | Add this line to your application's Gemfile:
12 |
13 | ```ruby
14 | gem 'system_tester', group: :development
15 | ```
16 |
17 | Add the system_tester db to `config/database.yml`
18 | ```yml
19 | # you may want to consider a shared MySQL/Postgres database
20 | # if you have a team that needs shared access
21 | system_tester:
22 | <<: *default
23 | database: db/system_tester.sqlite3
24 | ```
25 |
26 | And then install and run the migrations:
27 | ```bash
28 | $ bundle install
29 | $ rails system_tester:migrate
30 | ```
31 |
32 | Mount the engine in config/routes.rb:
33 | ```ruby
34 | Rails.application.routes.draw do
35 | # ... other routes
36 |
37 | # Mount in development environment only
38 | if Rails.env.development?
39 | mount SystemTester::Engine => "/system_tester"
40 | end
41 | end
42 | ```
43 |
44 | Start your dev server and you are good to go.
45 |
46 | ## Chrome extension
47 | [](https://youtu.be/bxHQKaIT7iM)
48 |
49 | The chrome extension provides a Devtools tab and acts as a client to this gem.
50 |
51 | **[ADD TO CHROME](https://chrome.google.com/webstore/detail/system-tester/ebpjncfolmfiiphibdajgblbchkklbcf)**
52 |
53 | ## Design
54 | System Tester is designed to work with a chrome extension, but could potentially be used for other applications as well.
55 | Run `rails routes` to see what endpoints are provided. The following design was set in place for the easy of reusing
56 | testing steps:
57 |
58 | * Features - the top level: one test script for a feature
59 | * Scenarios - 1:M assocation from Feature to Scenario. A Scenario is one test method.
60 | * Steps - Basically a line of code that can be an action or an assertion. STI is used to provide different step types.
61 | * ScenarioSteps - M:M assocation for Steps and Scenarios which also as a position attribute to allow for reordering.
62 | * Stairs - an ordered group of steps that can be reused.
63 | * StairSteps - M:M association to support stairs, Stair inherits from Step so the fk points back to the same table.
64 |
65 | ## License
66 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
67 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both threaded web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Attempt to read encrypted secrets from `config/secrets.yml.enc`.
18 | # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
19 | # `config/secrets.yml.key`.
20 | config.read_encrypted_secrets = true
21 |
22 | # Disable serving static files from the `/public` folder by default since
23 | # Apache or NGINX already handles this.
24 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
25 |
26 | # Compress JavaScripts and CSS.
27 | config.assets.js_compressor = :uglifier
28 | # config.assets.css_compressor = :sass
29 |
30 | # Do not fallback to assets pipeline if a precompiled asset is missed.
31 | config.assets.compile = false
32 |
33 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
34 |
35 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
36 | # config.action_controller.asset_host = 'http://assets.example.com'
37 |
38 | # Specifies the header that your server uses for sending files.
39 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
41 |
42 | # Mount Action Cable outside main process or domain
43 | # config.action_cable.mount_path = nil
44 | # config.action_cable.url = 'wss://example.com/cable'
45 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
46 |
47 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
48 | # config.force_ssl = true
49 |
50 | # Use the lowest log level to ensure availability of diagnostic information
51 | # when problems arise.
52 | config.log_level = :debug
53 |
54 | # Prepend all log lines with the following tags.
55 | config.log_tags = [ :request_id ]
56 |
57 | # Use a different cache store in production.
58 | # config.cache_store = :mem_cache_store
59 |
60 | # Use a real queuing backend for Active Job (and separate queues per environment)
61 | # config.active_job.queue_adapter = :resque
62 | # config.active_job.queue_name_prefix = "dummy_#{Rails.env}"
63 | config.action_mailer.perform_caching = false
64 |
65 | # Ignore bad email addresses and do not raise email delivery errors.
66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
67 | # config.action_mailer.raise_delivery_errors = false
68 |
69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
70 | # the I18n.default_locale when a translation cannot be found).
71 | config.i18n.fallbacks = true
72 |
73 | # Send deprecation notices to registered listeners.
74 | config.active_support.deprecation = :notify
75 |
76 | # Use default logging formatter so that PID and timestamp are not suppressed.
77 | config.log_formatter = ::Logger::Formatter.new
78 |
79 | # Use a different logger for distributed setups.
80 | # require 'syslog/logger'
81 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
82 |
83 | if ENV["RAILS_LOG_TO_STDOUT"].present?
84 | logger = ActiveSupport::Logger.new(STDOUT)
85 | logger.formatter = config.log_formatter
86 | config.logger = ActiveSupport::TaggedLogging.new(logger)
87 | end
88 |
89 | # Do not dump schema after migrations.
90 | config.active_record.dump_schema_after_migration = false
91 | end
92 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | system_tester (0.3.0)
5 | acts_as_list (~> 0.9.0)
6 | rack-cors
7 | rails (~> 5.1.0)
8 |
9 | GEM
10 | remote: https://rubygems.org/
11 | specs:
12 | actioncable (5.1.2)
13 | actionpack (= 5.1.2)
14 | nio4r (~> 2.0)
15 | websocket-driver (~> 0.6.1)
16 | actionmailer (5.1.2)
17 | actionpack (= 5.1.2)
18 | actionview (= 5.1.2)
19 | activejob (= 5.1.2)
20 | mail (~> 2.5, >= 2.5.4)
21 | rails-dom-testing (~> 2.0)
22 | actionpack (5.1.2)
23 | actionview (= 5.1.2)
24 | activesupport (= 5.1.2)
25 | rack (~> 2.0)
26 | rack-test (~> 0.6.3)
27 | rails-dom-testing (~> 2.0)
28 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
29 | actionview (5.1.2)
30 | activesupport (= 5.1.2)
31 | builder (~> 3.1)
32 | erubi (~> 1.4)
33 | rails-dom-testing (~> 2.0)
34 | rails-html-sanitizer (~> 1.0, >= 1.0.3)
35 | activejob (5.1.2)
36 | activesupport (= 5.1.2)
37 | globalid (>= 0.3.6)
38 | activemodel (5.1.2)
39 | activesupport (= 5.1.2)
40 | activerecord (5.1.2)
41 | activemodel (= 5.1.2)
42 | activesupport (= 5.1.2)
43 | arel (~> 8.0)
44 | activesupport (5.1.2)
45 | concurrent-ruby (~> 1.0, >= 1.0.2)
46 | i18n (~> 0.7)
47 | minitest (~> 5.1)
48 | tzinfo (~> 1.1)
49 | acts_as_list (0.9.7)
50 | activerecord (>= 3.0)
51 | arel (8.0.0)
52 | builder (3.2.3)
53 | byebug (9.0.6)
54 | codeclimate-test-reporter (1.0.8)
55 | simplecov (<= 0.13)
56 | concurrent-ruby (1.0.5)
57 | docile (1.1.5)
58 | erubi (1.6.1)
59 | fabrication (2.16.1)
60 | faker (1.7.3)
61 | i18n (~> 0.5)
62 | globalid (0.4.0)
63 | activesupport (>= 4.2.0)
64 | i18n (0.8.4)
65 | json (2.1.0)
66 | loofah (2.0.3)
67 | nokogiri (>= 1.5.9)
68 | mail (2.6.6)
69 | mime-types (>= 1.16, < 4)
70 | metaclass (0.0.4)
71 | method_source (0.8.2)
72 | mime-types (3.1)
73 | mime-types-data (~> 3.2015)
74 | mime-types-data (3.2016.0521)
75 | mini_portile2 (2.2.0)
76 | minitest (5.10.2)
77 | mocha (1.2.1)
78 | metaclass (~> 0.0.1)
79 | nio4r (2.1.0)
80 | nokogiri (1.8.0)
81 | mini_portile2 (~> 2.2.0)
82 | rack (2.0.3)
83 | rack-cors (0.4.1)
84 | rack-test (0.6.3)
85 | rack (>= 1.0)
86 | rails (5.1.2)
87 | actioncable (= 5.1.2)
88 | actionmailer (= 5.1.2)
89 | actionpack (= 5.1.2)
90 | actionview (= 5.1.2)
91 | activejob (= 5.1.2)
92 | activemodel (= 5.1.2)
93 | activerecord (= 5.1.2)
94 | activesupport (= 5.1.2)
95 | bundler (>= 1.3.0, < 2.0)
96 | railties (= 5.1.2)
97 | sprockets-rails (>= 2.0.0)
98 | rails-dom-testing (2.0.3)
99 | activesupport (>= 4.2.0)
100 | nokogiri (>= 1.6)
101 | rails-html-sanitizer (1.0.3)
102 | loofah (~> 2.0)
103 | railties (5.1.2)
104 | actionpack (= 5.1.2)
105 | activesupport (= 5.1.2)
106 | method_source
107 | rake (>= 0.8.7)
108 | thor (>= 0.18.1, < 2.0)
109 | rake (12.0.0)
110 | simplecov (0.13.0)
111 | docile (~> 1.1.0)
112 | json (>= 1.8, < 3)
113 | simplecov-html (~> 0.10.0)
114 | simplecov-html (0.10.1)
115 | sprockets (3.7.1)
116 | concurrent-ruby (~> 1.0)
117 | rack (> 1, < 3)
118 | sprockets-rails (3.2.0)
119 | actionpack (>= 4.0)
120 | activesupport (>= 4.0)
121 | sprockets (>= 3.0.0)
122 | sqlite3 (1.3.13)
123 | thor (0.19.4)
124 | thread_safe (0.3.6)
125 | tzinfo (1.2.3)
126 | thread_safe (~> 0.1)
127 | websocket-driver (0.6.5)
128 | websocket-extensions (>= 0.1.0)
129 | websocket-extensions (0.1.2)
130 |
131 | PLATFORMS
132 | ruby
133 |
134 | DEPENDENCIES
135 | byebug
136 | codeclimate-test-reporter (~> 1.0.0)
137 | fabrication
138 | faker
139 | mocha
140 | rack-cors
141 | simplecov
142 | sqlite3
143 | system_tester!
144 |
145 | BUNDLED WITH
146 | 1.15.1
147 |
--------------------------------------------------------------------------------
/test/integration/system_tester/steps_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | module SystemTester
4 | class StepsControllerTest < ActionDispatch::IntegrationTest
5 | def setup
6 | @click = Fabricate(:step, type: 'SystemTester::ClickOn')
7 | @fill = Fabricate(:step, type: 'SystemTester::FillIn')
8 | @visit = Fabricate(:step, type: 'SystemTester::Visit')
9 | @select = Fabricate(:step, type: 'SystemTester::Select')
10 | @assert_selector = Fabricate(:step, type: 'SystemTester::AssertSelector')
11 | @assert_text = Fabricate(:step, type: 'SystemTester::AssertText')
12 | @stair = Fabricate(:stair)
13 | # just test one step
14 | @step = @click
15 | end
16 |
17 | test "#index" do
18 | get '/system_tester/steps'
19 | step_from_response = get_step(JSON.parse(response.body))
20 | assert_match "click_on", step_from_response["to_s"]
21 | assert_response :success
22 | end
23 |
24 | test "#show" do
25 | get step_path
26 | assert_response :success
27 | end
28 |
29 | # TODO new endopint not being used by client
30 | # the intention is to preview the code before saving
31 | test "#new" do
32 | get '/system_tester/steps/new', params: {step: {title: "happy", type: "SystemTester::ClickOn"}}
33 | assert_response :success
34 | end
35 |
36 | test "#create" do
37 | assert_difference 'SystemTester::Step.count', 1 do
38 | post '/system_tester/steps', params: step_params
39 | end
40 | assert_response :success
41 | end
42 |
43 | test "#create invalid" do
44 | post '/system_tester/steps', params: step_params("")
45 | assert JSON.parse(response.body)["errors"]["title"].present?
46 | assert_response :unprocessable_entity
47 | end
48 |
49 | test "#create stair" do
50 | assert_difference 'SystemTester::Step.count', 1 do
51 | post '/system_tester/steps', params: step_params(nil, 'SystemTester::Stair')
52 | end
53 | assert_response :success
54 | end
55 |
56 | test "#update" do
57 | new_title = Faker::Lorem.words(2).join(" ")
58 | put step_path, params: step_params(new_title)
59 | assert_equal new_title, @step.reload.title
60 | assert_response :success
61 | end
62 |
63 | test "#update stair" do
64 | new_title = "New Stair Title"
65 | put stair_path, params: step_params(new_title, @stair.type)
66 | assert_equal new_title, @stair.reload.title
67 | assert File.exist?(Rails.root.join("test", "support", "system_tester", "new_stair_title.rb"))
68 | assert_response :success
69 | end
70 |
71 | test "#update one connected to a step and scenario" do
72 | Fabricate(:scenario_step, step: @step)
73 | Fabricate(:stair_step, step: @step)
74 | new_title = Faker::Lorem.words(2).join(" ")
75 | put step_path, params: step_params(new_title)
76 | assert_equal new_title, @step.reload.title
77 | assert_response :success
78 | end
79 |
80 | test "#update invalid" do
81 | put step_path, params: step_params("")
82 | assert JSON.parse(response.body)["errors"]["title"].present?
83 | assert_response :unprocessable_entity
84 | end
85 |
86 | test "#destroy" do
87 | assert_difference 'SystemTester::Step.count', -1 do
88 | delete step_path
89 | end
90 | assert_response :success
91 | end
92 |
93 | test "#destroy stair" do
94 | assert_difference 'SystemTester::Stair.count', -1 do
95 | delete stair_path
96 | end
97 | assert_response :success
98 | end
99 |
100 | private
101 |
102 | def step_path
103 | "/system_tester/steps/#{@step.id}"
104 | end
105 |
106 | def stair_path
107 | "/system_tester/steps/#{@stair.id}"
108 | end
109 |
110 | def step_params(title=nil, type=nil)
111 | title = title || Faker::Lorem.words(2).join(" ")
112 | {
113 | step: {
114 | title: title,
115 | type: type || @step.type,
116 | arg_one: @step.arg_one,
117 | arg_two: @step.arg_two
118 | }
119 | }
120 | end
121 |
122 | def get_step(response)
123 | response.select { |f| f["id"] == @step.id }.first
124 | end
125 | end
126 | end
--------------------------------------------------------------------------------