├── .github └── workflows │ ├── ci.yml │ ├── pr-linter.yml │ └── release.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .ruby-gemset ├── .travis.yml ├── .yardopts ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.selenium3 ├── ISSUE_TEMPLATE.md ├── LICENSE ├── MAINTENANCE.md ├── README.md ├── Rakefile ├── bin └── howitzer ├── features ├── cli_help.feature ├── cli_new.feature ├── cli_unknown.feature ├── cli_update.feature ├── cli_version.feature ├── step_definitions │ └── common_steps.rb └── support │ └── env.rb ├── generators ├── base_generator.rb ├── config │ ├── config_generator.rb │ └── templates │ │ ├── boot.rb │ │ ├── capybara.rb │ │ ├── custom.yml │ │ ├── default.yml │ │ └── drivers │ │ ├── browserstack.rb │ │ ├── crossbrowsertesting.rb │ │ ├── headless_chrome.rb │ │ ├── headless_firefox.rb │ │ ├── lambdatest.rb │ │ ├── sauce.rb │ │ ├── selenium.rb │ │ ├── selenium_grid.rb │ │ └── testingbot.rb ├── cucumber │ ├── cucumber_generator.rb │ └── templates │ │ ├── common_steps.rb │ │ ├── cucumber.rake │ │ ├── cuke_sniffer.rake │ │ ├── env.rb │ │ ├── example.feature │ │ ├── hooks.rb │ │ └── transformers.rb ├── emails │ ├── emails_generator.rb │ └── templates │ │ └── example_email.rb ├── prerequisites │ ├── prerequisites_generator.rb │ └── templates │ │ ├── base.rb │ │ ├── factory_bot.rb │ │ ├── user.rb │ │ └── users.rb ├── root │ ├── root_generator.rb │ └── templates │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .rubocop.yml.erb │ │ ├── Dockerfile │ │ ├── Gemfile.erb │ │ ├── README.md.erb │ │ ├── Rakefile │ │ └── docker-compose.yml.erb ├── rspec │ ├── rspec_generator.rb │ └── templates │ │ ├── example_spec.rb │ │ ├── rspec.rake │ │ └── spec_helper.rb ├── tasks │ ├── tasks_generator.rb │ └── templates │ │ └── common.rake ├── turnip │ ├── templates │ │ ├── .rspec │ │ ├── common_steps.rb │ │ ├── example.feature │ │ ├── spec_helper.rb │ │ ├── turnip.rake │ │ └── turnip_helper.rb │ └── turnip_generator.rb └── web │ ├── templates │ ├── example_page.rb │ └── menu_section.rb │ └── web_generator.rb ├── howitzer.gemspec ├── lib ├── howitzer.rb └── howitzer │ ├── cache.rb │ ├── capybara_helpers.rb │ ├── email.rb │ ├── exceptions.rb │ ├── gmail_api.rb │ ├── gmail_api │ └── client.rb │ ├── log.rb │ ├── mail_adapters.rb │ ├── mail_adapters │ ├── abstract.rb │ ├── gmail.rb │ ├── mailgun.rb │ ├── mailtrap.rb │ ├── onesecmail.rb │ └── testmail.rb │ ├── mailgun_api.rb │ ├── mailgun_api │ ├── client.rb │ ├── connector.rb │ └── response.rb │ ├── mailtrap_api.rb │ ├── mailtrap_api │ └── client.rb │ ├── meta.rb │ ├── meta │ ├── actions.rb │ ├── element.rb │ ├── entry.rb │ ├── iframe.rb │ └── section.rb │ ├── onesecmail_api.rb │ ├── onesecmail_api │ └── client.rb │ ├── tasks │ └── framework.rake │ ├── testmail_api.rb │ ├── testmail_api │ └── client.rb │ ├── utils.rb │ ├── utils │ ├── argument_convertable.rb │ └── string_extensions.rb │ ├── version.rb │ ├── web.rb │ └── web │ ├── base_section.rb │ ├── blank_page.rb │ ├── capybara_context_holder.rb │ ├── capybara_methods_proxy.rb │ ├── element_dsl.rb │ ├── iframe_dsl.rb │ ├── page.rb │ ├── page_dsl.rb │ ├── page_validator.rb │ ├── section.rb │ └── section_dsl.rb └── spec ├── config └── custom.yml ├── spec_helper.rb ├── support ├── generator_helper.rb ├── logger_helper.rb └── shared_examples │ ├── capybara_context_holder.rb │ ├── capybara_methods_proxy.rb │ ├── dynamic_section_methods.rb │ ├── element_dsl.rb │ └── meta_highlight_xpath.rb └── unit ├── generators ├── base_generator_spec.rb ├── config_generator_spec.rb ├── cucumber_generator_spec.rb ├── emails_generator_spec.rb ├── prerequisites_generator_spec.rb ├── root_generator_spec.rb ├── rspec_generator_spec.rb ├── tasks_generator_spec.rb ├── templates │ ├── cucumber_spec.rb │ ├── rspec_spec.rb │ └── turnip_spec.rb ├── turnip_generator_spec.rb └── web_generator_spec.rb ├── lib ├── cache_spec.rb ├── capybara_helpers_spec.rb ├── email_spec.rb ├── gmail_api │ └── client_spec.rb ├── howitzer_spec.rb ├── init_spec.rb ├── log_spec.rb ├── mail_adapters │ ├── abstract_spec.rb │ ├── gmail_spec.rb │ ├── mailgun_spec.rb │ ├── mailtrap_spec.rb │ ├── onesecmail_spec.rb │ └── testmail_spec.rb ├── mailgun_api │ ├── client_spec.rb │ ├── connector_spec.rb │ └── response_spec.rb ├── mailtrap_api │ └── client_spec.rb ├── meta │ ├── element_spec.rb │ ├── entry_spec.rb │ ├── iframe_spec.rb │ └── section_spec.rb ├── onesecmail_api │ └── client_spec.rb ├── testmail_api │ └── client_spec.rb ├── utils │ └── string_extensions_spec.rb └── web │ ├── base_section_spec.rb │ ├── element_dsl_spec.rb │ ├── iframe_dsl_spec.rb │ ├── page_dsl_spec.rb │ ├── page_spec.rb │ ├── page_validator_spec.rb │ ├── section_dsl_spec.rb │ └── section_spec.rb └── version_spec.rb /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Howitzer 2 | 3 | on: 4 | pull_request: 5 | branches: master 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | CI: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | ruby-version: 20 | - 2.7.7 21 | - 3.0.5 22 | - 3.1.3 23 | - 3.2.0 24 | gemfile: 25 | - Gemfile 26 | - Gemfile.selenium3 27 | 28 | env: 29 | BUNDLE_GEMFILE: ${{ matrix.gemfile }} 30 | steps: 31 | - uses: actions/checkout@v3 32 | - name: Set up Ruby ${{ matrix.ruby-version }} 33 | uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: ${{ matrix.ruby-version }} 36 | bundler-cache: true 37 | - name: Install dependencies 38 | run: bundle install 39 | - name: Run rubocop 40 | run: bundle exec rake rubocop 41 | - name: Run yard:validate 42 | run: bundle exec rake yard:validate 43 | - name: Run spec 44 | run: bundle exec rake spec 45 | - name: Run cucumber 46 | run: bundle exec rake cucumber 47 | -------------------------------------------------------------------------------- /.github/workflows/pr-linter.yml: -------------------------------------------------------------------------------- 1 | name: "Lint Pull Request" 2 | 3 | permissions: 4 | id-token: write 5 | contents: read 6 | checks: write 7 | actions: read 8 | statuses: read 9 | pull-requests: read 10 | issues: read 11 | 12 | on: 13 | pull_request_target: 14 | types: 15 | - opened 16 | - edited 17 | - synchronize 18 | 19 | jobs: 20 | main: 21 | name: Validate PR title 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: amannn/action-semantic-pull-request@v5 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release-please: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: google-github-actions/release-please-action@v3 13 | id: release 14 | with: 15 | release-type: ruby 16 | package-name: howitzer 17 | bump-minor-pre-major: true 18 | bump-patch-for-minor-pre-major: true 19 | version-file: "lib/howitzer/version.rb" 20 | extra-files: '.deploy/Chart.yaml' 21 | - uses: actions/checkout@v3 22 | with: 23 | fetch-depth: 0 24 | if: ${{ steps.release.outputs.release_created }} 25 | - uses: ruby/setup-ruby@v1 26 | with: 27 | ruby-version: 3.0.4 28 | bundler-cache: true 29 | if: ${{ steps.release.outputs.release_created }} 30 | - run: bundle install 31 | if: ${{ steps.release.outputs.release_created }} 32 | - name: Publish gem 33 | run: | 34 | git config user.name "GitHub Actions Bot" 35 | git config user.email "<>" 36 | bundle exec rake release 37 | env: 38 | GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" 39 | if: ${{ steps.release.outputs.release_created }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | .idea 3 | .rvmrc 4 | *.gem 5 | vendor/bundle/* 6 | spec/log/* 7 | Gemfile.lock 8 | Gemfile.selenium3.lock 9 | doc 10 | .yardoc 11 | tmp/* 12 | .bundle 13 | **/.DS_Store 14 | .ruby-version 15 | .byebug_history 16 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require fuubar 3 | --format Fuubar -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # See full list of defaults here: https://github.com/bbatsov/rubocop/blob/master/config/default.yml 2 | # To see all cops used see here: https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml 3 | 4 | AllCops: 5 | TargetRubyVersion: 2.7 6 | NewCops: enable 7 | DisplayCopNames: true 8 | 9 | Gemspec/RequireMFA: 10 | Enabled: false 11 | 12 | Layout/CaseIndentation: 13 | Enabled: false 14 | 15 | Layout/LineLength: 16 | Max: 120 17 | 18 | Lint/AmbiguousBlockAssociation: 19 | Enabled: false 20 | 21 | Lint/AmbiguousRegexpLiteral: 22 | Enabled: false 23 | 24 | Lint/ConstantDefinitionInBlock: 25 | Exclude: 26 | - 'spec/unit/lib/web/iframe_dsl_spec.rb' 27 | 28 | Metrics/BlockLength: 29 | Enabled: false 30 | 31 | Metrics/MethodLength: 32 | Max: 30 33 | 34 | Metrics/ModuleLength: 35 | Max: 150 36 | 37 | Style/CaseEquality: 38 | Enabled: false 39 | 40 | Style/EmptyElse: 41 | Enabled: false 42 | 43 | Style/EvalWithLocation: 44 | Enabled: false 45 | 46 | Style/FormatStringToken: 47 | Enabled: false 48 | 49 | Style/FrozenStringLiteralComment: 50 | Enabled: false 51 | 52 | Style/MixinGrouping: 53 | EnforcedStyle: separated 54 | Exclude: 55 | - '**/*_steps.rb' 56 | - 'tmp/**' 57 | 58 | Style/MixinUsage: 59 | Enabled: false 60 | 61 | Style/RescueStandardError: 62 | Enabled: false 63 | 64 | Style/TrivialAccessors: 65 | AllowDSLWriters: true 66 | 67 | Style/YodaCondition: 68 | Enabled: false 69 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | howitzer -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | before_install: 3 | - gem install bundler 4 | rvm: 5 | - 2.6.8 6 | - 2.7.4 7 | - 3.0.2 8 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | lib/**/*.rb 2 | - 3 | CONTRIBUTING.md 4 | LICENSE 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Howitzer 2 | 3 | We love pull requests from everyone. 4 | 5 | To contribute to Howitzer: 6 | 7 | 1. Fork the [official repository](https://github.com/strongqa/howitzer/tree/master). 8 | 2. Make your changes in a topic branch. 9 | 3. Send a pull request. 10 | 11 | Notes: 12 | 13 | * Contributions without tests won't be accepted. 14 | * Please don't update the Gem version. -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | # Specify your gem's dependencies in howitzer.gemspec 3 | group :test do 4 | gem 'codecov', require: false 5 | gem 'gmail', require: false 6 | gem 'net-imap', require: false 7 | gem 'net-smtp', require: false 8 | gem 'pry' 9 | gem 'pry-byebug' 10 | gem 'repeater', require: false 11 | gem 'rest-client', require: false 12 | gem 'simplecov', require: false 13 | end 14 | gemspec 15 | 16 | group :development do 17 | gem 'aruba' 18 | gem 'fakeweb', git: 'https://github.com/chrisk/fakeweb.git', branch: 'master' 19 | gem 'ffaker' 20 | gem 'fuubar' 21 | gem 'rubocop' 22 | gem 'yard' 23 | end 24 | -------------------------------------------------------------------------------- /Gemfile.selenium3: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | # Specify your gem's dependencies in howitzer.gemspec 3 | group :test do 4 | gem 'codecov', require: false 5 | gem 'gmail', require: false 6 | gem 'net-imap', require: false 7 | gem 'net-smtp', require: false 8 | gem 'pry' 9 | gem 'pry-byebug' 10 | gem 'repeater', require: false 11 | gem 'rest-client', require: false 12 | gem 'simplecov', require: false 13 | gem 'selenium-webdriver', '< 4.0.0.alpha1', require: false 14 | end 15 | gemspec 16 | 17 | group :development do 18 | gem 'aruba' 19 | gem 'fakeweb', git: 'https://github.com/chrisk/fakeweb.git', branch: 'master' 20 | gem 'ffaker' 21 | gem 'fuubar' 22 | gem 'rubocop' 23 | gem 'yard' 24 | end 25 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Meta 2 | Howitzer Version: 3 | 4 | Driver and browser information: 5 | 6 | Gem Versions: 7 | 8 | 9 | ## Expected Behavior 10 | 11 | ## Actual Behavior 12 | 13 | ## Steps to reproduce 14 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2021 Roman Parashchenko and StrongQA, LLC. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /MAINTENANCE.md: -------------------------------------------------------------------------------- 1 | # Howitzer Maintenance 2 | 3 | This guide provides detailed instructions how to release a new Howitzer version 4 | 5 | To release a new Howitzer version: 6 | 7 | * Make sure all pull requests have been merged to master branch 8 | * Make sure last build is passed in [TravisCI](https://app.travis-ci.com/github/strongqa/howitzer) 9 | * Make sure the code is covered 100% in [Codecov](https://codecov.io/gh/strongqa/howitzer/branch/master) 10 | * Make sure the code is documented 100% with following command: 11 | ``` 12 | rake yard 13 | ``` 14 | * [Upgrade](https://github.com/strongqa/howitzer/wiki/Migration-to-new-version) Howitzer examples [Cucumber](https://github.com/strongqa/howitzer_example_cucumber), [Rspec](https://github.com/strongqa/howitzer_example_rspec) and [Turnip](https://github.com/strongqa/howitzer_example_turnip) to last version of code from master and make sure all builds are green 15 | * Bump [version](lib/howitzer/version.rb). Please note howitzer uses [semantic versioning](https://semver.org/) 16 | * Verify and actualize [ChangeLog](CHANGELOG.md) 17 | * Commit all changes and push to origin master 18 | * Specify credentials for Rubygems.org (once only) with following commands: 19 | ```bash 20 | curl https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials 21 | chmod 0600 ~/.gem/credentials 22 | ``` 23 | * Release Gem with following command: 24 | ```bash 25 | rake release 26 | ``` 27 | * Verify successful release on [Rubygems](https://rubygems.org/gems/howitzer) 28 | * Force API documentation indexing for the new version on [Rubygems](https://rubygems.org/gems/howitzer) 29 | * Update new link to documentation on [web site](https://github.com/romikoops/howitzer-framework.io/tree/gh-pages) Note: The web site will be updated automatically after pushing code to Github 30 | * Update [Howitzer Guides](https://github.com/strongqa/docs.howitzer-framework.io/blob/gh-pages/README.md) regarding new changes 31 | * Notify Community (Gitter, Twitter, Google Group) about the new release 32 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | Bundler.setup 4 | 5 | require 'rake' 6 | require 'yard' 7 | require 'stringio' 8 | require 'rspec/core/rake_task' 9 | require 'cucumber/rake/task' 10 | require 'rubocop/rake_task' 11 | 12 | Bundler::GemHelper.install_tasks 13 | RSpec::Core::RakeTask.new(:spec) { |_spec| nil } 14 | 15 | Cucumber::Rake::Task.new(:cucumber, 'Run all cucumber features') do |t| 16 | t.fork = false 17 | t.cucumber_opts = %w[--publish-quiet] 18 | end 19 | 20 | RuboCop::RakeTask.new 21 | 22 | YARD::Rake::YardocTask.new { |_t| nil } 23 | 24 | namespace :yard do 25 | desc 'Validate yard coverage' 26 | task :validate do 27 | log = StringIO.new 28 | YARD::Logger.instance(log) 29 | doc = YARD::CLI::Yardoc.new 30 | doc.use_document_file = false 31 | doc.use_yardopts_file = false 32 | doc.generate = false 33 | doc.run('stats --list-undoc') 34 | output = log.string 35 | puts output 36 | exit(1) unless output.include?('100.00% documented') 37 | end 38 | end 39 | 40 | task default: %i[rubocop yard:validate spec cucumber] 41 | -------------------------------------------------------------------------------- /features/cli_help.feature: -------------------------------------------------------------------------------- 1 | Feature: Howitzer CLI Help 2 | 3 | Scenario Outline: Run with help global option 4 | When I run `howitzer