howitzer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/Gemfile +4 -0
  2. data/Gemfile.lock +113 -0
  3. data/LICENSE +22 -0
  4. data/README.md +44 -0
  5. data/Rakefile +2 -0
  6. data/bin/howitzer +41 -0
  7. data/generators/config/config_generator.rb +24 -0
  8. data/generators/config/templates/cucumber.yml +11 -0
  9. data/generators/config/templates/custom.yml +4 -0
  10. data/generators/config/templates/default.yml +76 -0
  11. data/generators/cucumber/cucumber_generator.rb +31 -0
  12. data/generators/cucumber/templates/common_steps.rb +23 -0
  13. data/generators/cucumber/templates/env.rb +38 -0
  14. data/generators/cucumber/templates/example.feature +16 -0
  15. data/generators/cucumber/templates/transformers.rb +28 -0
  16. data/generators/emails/emails_generator.rb +23 -0
  17. data/generators/emails/templates/example_email.rb +7 -0
  18. data/generators/pages/pages_generator.rb +23 -0
  19. data/generators/pages/templates/example_menu.rb +14 -0
  20. data/generators/pages/templates/example_page.rb +15 -0
  21. data/generators/root/root_generator.rb +25 -0
  22. data/generators/root/templates/.gitignore +20 -0
  23. data/generators/root/templates/Gemfile +4 -0
  24. data/generators/root/templates/Rakefile +4 -0
  25. data/generators/root/templates/boot.rb +16 -0
  26. data/generators/tasks/tasks_generator.rb +22 -0
  27. data/generators/tasks/templates/cucumber.rake +57 -0
  28. data/howitzer.gemspec +36 -0
  29. data/lib/howitzer.rb +5 -0
  30. data/lib/howitzer/helpers.rb +58 -0
  31. data/lib/howitzer/init.rb +5 -0
  32. data/lib/howitzer/utils.rb +14 -0
  33. data/lib/howitzer/utils/capybara_patched.rb +22 -0
  34. data/lib/howitzer/utils/capybara_settings.rb +110 -0
  35. data/lib/howitzer/utils/data_generator/data_storage.rb +41 -0
  36. data/lib/howitzer/utils/data_generator/gen.rb +89 -0
  37. data/lib/howitzer/utils/email/email.rb +46 -0
  38. data/lib/howitzer/utils/email/mail_client.rb +126 -0
  39. data/lib/howitzer/utils/email/mailgun.rb +175 -0
  40. data/lib/howitzer/utils/email/mailgun_helper.rb +35 -0
  41. data/lib/howitzer/utils/locator_store.rb +118 -0
  42. data/lib/howitzer/utils/logger.rb +108 -0
  43. data/lib/howitzer/version.rb +3 -0
  44. data/lib/howitzer/web_page.rb +62 -0
  45. metadata +334 -0
@@ -0,0 +1,16 @@
1
+ Feature: Addition
2
+ In order to avoid silly mistakes
3
+ As a math idiot
4
+ I want to be told the sum of two numbers
5
+
6
+ Scenario Outline: Add two numbers
7
+ Given I have entered <input_1> into the calculator
8
+ And I have entered <input_2> into the calculator
9
+ When I press <button>
10
+ Then the result should be <output> on the screen
11
+
12
+ Examples:
13
+ | input_1 | input_2 | button | output |
14
+ | 20 | 30 | add | 50 |
15
+ | 2 | 5 | add | 7 |
16
+ | 0 | 40 | add | 40 |
@@ -0,0 +1,28 @@
1
+ #############################################################
2
+ # TRANSFORMERS #
3
+ #############################################################
4
+ Transform /UNIQ_USER(\d*)(?:\[\:(.+)\])?/ do |num, property|
5
+ res = Gen::given_user_by_number(num)
6
+ res = res.send(property) if property
7
+ res
8
+ end
9
+
10
+ Transform /^table:.*$/ do |table|
11
+ raw = table.raw.map do |array|
12
+ array.map do |el|
13
+ res = el
14
+
15
+ # UNIQ_USER
16
+ data = /UNIQ_USER(?<num>\d*)(?:\[\:(?<property>.+)\])?/.match(el)
17
+ if data
18
+ res = Gen::given_user_by_number(data[:num])
19
+ if data[:property]
20
+ res = res.send(data[:property])
21
+ end
22
+ end
23
+
24
+ res
25
+ end
26
+ end
27
+ Cucumber::Ast::Table.new(raw)
28
+ end
@@ -0,0 +1,23 @@
1
+ require 'rbconfig'
2
+
3
+ class EmailsGenerator < RubiGen::Base
4
+
5
+ def initialize(runtime_args, runtime_options = {})
6
+ super
7
+ @destination_root = File.expand_path('emails')
8
+ end
9
+
10
+ def manifest
11
+ record do |m|
12
+ m.directory ''
13
+ m.template 'example_email.rb', 'example_email.rb'
14
+ end
15
+ end
16
+
17
+ protected
18
+ def banner
19
+ <<-EOS
20
+ Creates a simple email class."
21
+ EOS
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ class TestEmail < Email
2
+ SUBJECT = "Test email"
3
+
4
+ def addressed_to?(new_user)
5
+ /Hi #{new_user}/ === plain_text_body
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ require 'rbconfig'
2
+
3
+ class PagesGenerator < RubiGen::Base
4
+ def initialize(runtime_args, runtime_options = {})
5
+ super
6
+ @destination_root = File.expand_path('pages')
7
+ end
8
+
9
+ def manifest
10
+ record do |m|
11
+ m.directory ''
12
+ m.template 'example_page.rb', 'example_page.rb'
13
+ m.template 'example_menu.rb', 'example_menu.rb'
14
+ end
15
+ end
16
+
17
+ protected
18
+ def banner
19
+ <<-EOS
20
+ Creates PageOriented pattern structure
21
+ EOS
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module ExampleMenu
2
+ def self.included(base)
3
+ base.class_eval do
4
+ add_locator :menu_button, ".menuButton"
5
+ add_locator :account, xpath: ".//*[@id='metaMenu']//a[contains(., 'Account')]"
6
+ add_locator :log_out, xpath: ".//*[@id='metaMenu']//a[contains(., 'Log Out')]"
7
+ end
8
+ end
9
+
10
+ def open_menu
11
+ log.info "Open menu"
12
+ click_link locator(:menu_button)
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'example_menu'
2
+
3
+ class ExamplePage < WebPage
4
+ URL = '/'
5
+ URL_PATTERN = /#{Regexp.escape(settings.app_host)}\/?/
6
+
7
+ add_field_locator :search_input, 'lst-ib'
8
+ add_button_locator :search_btn, 'btnK'
9
+
10
+ include ExampleMenu
11
+
12
+ def fill_keyword(data)
13
+ fill_in field_locator(:search_input), data
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ require 'rbconfig'
2
+
3
+ class RootGenerator < RubiGen::Base
4
+ def initialize(runtime_args, runtime_options = {})
5
+ super
6
+ @destination_root = File.expand_path('')
7
+ end
8
+
9
+ def manifest
10
+ record do |m|
11
+ m.directory ''
12
+ m.template '.gitignore', '.gitignore'
13
+ m.template 'Gemfile', 'Gemfile'
14
+ m.template 'Rakefile', 'Rakefile'
15
+ m.template 'boot.rb', 'boot.rb'
16
+ end
17
+ end
18
+
19
+ protected
20
+ def banner
21
+ <<-EOF
22
+ Creates root config files.
23
+ EOF
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ .idea/
2
+ custom.yml
3
+ bin/
4
+ log/
5
+ eylogs/
6
+ spec/results/
7
+ spec/sandbox/
8
+ tmp/
9
+ *.swp
10
+ *.orig
11
+ .rakeTasks
12
+ .bundle
13
+ .DS_STORE
14
+ *.xml
15
+ *.log
16
+ *.pem
17
+ build-number.txt
18
+ sauce_connect.log*
19
+ *.*~
20
+ capybara-*.html
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+ source "http://gemcutter.org"
3
+
4
+ gem 'howitzer'
@@ -0,0 +1,4 @@
1
+ require 'rake'
2
+
3
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
4
+ ENV['RAKE_TASK'] = ARGV[0] if /^(?:r?spec|cucumber)/ === ARGV[0]
@@ -0,0 +1,16 @@
1
+ require 'howitzer'
2
+
3
+ Dir.chdir(File.join(File.dirname(__FILE__), '.'))
4
+
5
+ def settings
6
+ SexySettings::Base.instance()
7
+ end
8
+
9
+ if settings.required_clean_logs
10
+ require 'rake/clean'
11
+ CLEAN.include("#{settings.log_dir}/*")
12
+ Rake::Task[:clean].invoke
13
+ end
14
+
15
+ Dir[File.join(File.dirname(__FILE__), "./emails/*.rb")].each {|f| require f}
16
+ Dir[File.join(File.dirname(__FILE__), "./pages/*.rb")].each {|f| require f}
@@ -0,0 +1,22 @@
1
+ require 'rbconfig'
2
+
3
+ class TasksGenerator < RubiGen::Base
4
+ def initialize(runtime_args, runtime_options = {})
5
+ super
6
+ @destination_root = File.expand_path('tasks')
7
+ end
8
+
9
+ def manifest
10
+ record do |m|
11
+ m.directory ''
12
+ m.template 'cucumber.rake', 'cucumber.rake'
13
+ end
14
+ end
15
+
16
+ protected
17
+ def banner
18
+ <<-EOF
19
+ Creates RAKE tasks folder and file.
20
+ EOF
21
+ end
22
+ end
@@ -0,0 +1,57 @@
1
+
2
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
3
+ begin
4
+ require 'cucumber'
5
+ require 'cucumber/rake/task'
6
+
7
+ namespace :cucumber do
8
+ Cucumber::Rake::Task.new({ok: 'db:test:prepare'}, 'Run features that should pass') do |t|
9
+ t.fork = false # You may get faster startup if you set this to false
10
+ t.profile = 'default'
11
+ end
12
+
13
+ Cucumber::Rake::Task.new({wip: 'db:test:prepare'}, 'Run features that are being worked on') do |t|
14
+ t.fork = false # You may get faster startup if you set this to false
15
+ t.profile = 'wip'
16
+ end
17
+
18
+ Cucumber::Rake::Task.new({bug: 'db:test:prepare'}, 'Run features with known bugs') do |t|
19
+ t.fork = false # You may get faster startup if you set this to false
20
+ t.profile = 'bug'
21
+ end
22
+
23
+ Cucumber::Rake::Task.new({demo: 'db:test:prepare'}, 'Run demo feature') do |t|
24
+ t.fork = false # You may get faster startup if you set this to false
25
+ t.profile = 'demo'
26
+ end
27
+
28
+ Cucumber::Rake::Task.new({rerun: 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
29
+ t.fork = false # You may get faster startup if you set this to false
30
+ t.profile = 'rerun'
31
+ end
32
+
33
+ desc 'Run all features'
34
+ task all: [:ok, :wip]
35
+
36
+ end
37
+ desc 'Alias for cucumber:ok'
38
+ task cucumber: 'cucumber:ok'
39
+
40
+ task default: :cucumber
41
+
42
+ task features: :cucumber do
43
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
44
+ end
45
+
46
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
47
+ task 'db:test:prepare' do
48
+ end
49
+
50
+ rescue LoadError
51
+ desc 'cucumber rake task not available (cucumber not installed)'
52
+ task :cucumber do
53
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
54
+ end
55
+ end
56
+
57
+ end
data/howitzer.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/howitzer/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Roman Parashchenko, Konstantin Lynda, Nikolay Zozulyak"]
6
+ gem.email = ["strongqa@gmail.com"]
7
+ gem.description = %q{The framework is based on Page Object pattern, Capybara and Rspec/Cucumber libraries}
8
+ gem.summary = %q{Universal Ruby Test Framework for black box testing}
9
+ gem.homepage = "https://github.com/romikoops/howitzer"
10
+
11
+ gem.bindir = 'bin'
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "howitzer"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Howitzer::VERSION
18
+ gem.required_ruby_version = '~> 1.9.2'
19
+
20
+ gem.add_runtime_dependency 'rake'
21
+ gem.add_runtime_dependency 'rubigen'
22
+ gem.add_runtime_dependency 'i18n'
23
+ gem.add_runtime_dependency 'cucumber'
24
+ gem.add_runtime_dependency 'rspec', '~> 2.0'
25
+ gem.add_runtime_dependency 'sexy_settings'
26
+ gem.add_runtime_dependency 'repeater'
27
+ gem.add_runtime_dependency 'selenium-webdriver'
28
+ gem.add_runtime_dependency 'capybara'
29
+ gem.add_runtime_dependency 'launchy'
30
+ gem.add_runtime_dependency 'log4r'
31
+ gem.add_runtime_dependency 'mail'
32
+ gem.add_runtime_dependency 'rest-client'
33
+ gem.add_runtime_dependency 'poltergeist'
34
+ gem.add_runtime_dependency 'activeresource', '3.2.8'
35
+
36
+ end
data/lib/howitzer.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "howitzer/version"
2
+ require 'howitzer/utils'
3
+ require 'howitzer/init'
4
+ require 'howitzer/helpers'
5
+ require 'howitzer/web_page'
@@ -0,0 +1,58 @@
1
+
2
+ def sauce_driver?
3
+ settings.driver.to_sym == :sauce
4
+ end
5
+
6
+ def selenium_driver?
7
+ settings.driver.to_sym == :selenium
8
+ end
9
+
10
+ def ie_browser?
11
+ ie_browsers = [:ie, :iexplore]
12
+ if sauce_driver?
13
+ ie_browsers.include?(settings.sl_browser_name.to_sym)
14
+ elsif selenium_driver?
15
+ ie_browsers.include?(settings.sel_browser.to_sym)
16
+ end
17
+ end
18
+
19
+ def ff_browser?
20
+ ff_browsers = [:ff, :firefox]
21
+ if sauce_driver?
22
+ ff_browsers.include?(settings.sl_browser_name.to_sym)
23
+ elsif selenium_driver?
24
+ ff_browsers.include?(settings.sel_browser.to_sym)
25
+ end
26
+ end
27
+
28
+
29
+ def duration(time_in_numeric)
30
+ secs = time_in_numeric.to_i
31
+ mins = secs / 60
32
+ hours = mins / 60
33
+ if hours > 0
34
+ "[#{hours}h #{mins % 60}m #{secs % 60}s]"
35
+ elsif mins > 0
36
+ "[#{mins}m #{secs % 60}s]"
37
+ elsif secs >= 0
38
+ "[0m #{secs}s]"
39
+ end
40
+ end
41
+
42
+ def ri(value)
43
+ raise value.inspect
44
+ end
45
+
46
+ class String
47
+ def open(*args)
48
+ as_page_class.open(*args)
49
+ end
50
+
51
+ def given
52
+ as_page_class.new
53
+ end
54
+
55
+ def as_page_class
56
+ Object.const_get("#{self.capitalize}Page")
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ include DataGenerator
2
+ include Capybara::DSL #TODO should be included to webpage instead of global content
3
+
4
+ # Configure mail client
5
+ Mailgun::init(settings.mailgun_api_key)
@@ -0,0 +1,14 @@
1
+ require 'sexy_settings'
2
+ require 'repeater'
3
+
4
+ SexySettings.configure do |config|
5
+ config.path_to_default_settings = File.expand_path("config/default.yml", Dir.pwd)
6
+ config.path_to_custom_settings = File.expand_path("config/custom.yml", Dir.pwd)
7
+ end
8
+
9
+ def settings
10
+ SexySettings::Base.instance()
11
+ end
12
+
13
+
14
+ Dir[File.join(File.dirname(__FILE__), "./utils/**/*.rb")].each {|f| require f}
@@ -0,0 +1,22 @@
1
+ module CapybaraPatched
2
+ class Capybara::Selenium::PatchedDriver < Capybara::Selenium::Driver
3
+ RETRY_ON = [
4
+ ::Selenium::WebDriver::Error::UnhandledError,
5
+ ::Selenium::WebDriver::Error::UnknownError,
6
+ ::Selenium::WebDriver::Error::InvalidSelectorError
7
+ ]
8
+
9
+ # workaround for transferring correct arguments via call stack
10
+ Capybara::Session.instance_eval do
11
+ self::NODE_METHODS.each do |method|
12
+ class_eval <<-RUBY
13
+ def #{method}(*args, &block)
14
+ retryable(tries:3, logger: log, trace: true, on: RETRY_ON) do
15
+ current_node.send(:#{method}, *args.flatten, &block)
16
+ end
17
+ end
18
+ RUBY
19
+ end
20
+ end
21
+ end
22
+ end