pagemodels 0.1.0

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 (51) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.txt +58 -0
  4. data/Rakefile +7 -0
  5. data/examples/rails_and_cucumber/.gitignore +4 -0
  6. data/examples/rails_and_cucumber/Gemfile +11 -0
  7. data/examples/rails_and_cucumber/README.txt +23 -0
  8. data/examples/rails_and_cucumber/Rakefile +7 -0
  9. data/examples/rails_and_cucumber/app/controllers/application_controller.rb +3 -0
  10. data/examples/rails_and_cucumber/app/controllers/financial_reports_controller.rb +7 -0
  11. data/examples/rails_and_cucumber/app/models/transaction.rb +25 -0
  12. data/examples/rails_and_cucumber/app/views/financial_reports/show.html.erb +20 -0
  13. data/examples/rails_and_cucumber/app/views/layouts/application.html.erb +14 -0
  14. data/examples/rails_and_cucumber/config/application.rb +18 -0
  15. data/examples/rails_and_cucumber/config/boot.rb +6 -0
  16. data/examples/rails_and_cucumber/config/cucumber.yml +8 -0
  17. data/examples/rails_and_cucumber/config/environment.rb +5 -0
  18. data/examples/rails_and_cucumber/config/environments/development.rb +23 -0
  19. data/examples/rails_and_cucumber/config/environments/test.rb +30 -0
  20. data/examples/rails_and_cucumber/config/initializers/secret_token.rb +7 -0
  21. data/examples/rails_and_cucumber/config/initializers/session_store.rb +8 -0
  22. data/examples/rails_and_cucumber/config/routes.rb +3 -0
  23. data/examples/rails_and_cucumber/features/financial_reporting.feature +29 -0
  24. data/examples/rails_and_cucumber/features/pagemodels/financial_report_page.rb +29 -0
  25. data/examples/rails_and_cucumber/features/step_definitions/financial_reporting_steps.rb +14 -0
  26. data/examples/rails_and_cucumber/features/support/env.rb +13 -0
  27. data/examples/rails_and_cucumber/lib/tasks/cucumber.rake +57 -0
  28. data/examples/rails_and_cucumber/script/cucumber +10 -0
  29. data/examples/rails_and_cucumber/script/rails +6 -0
  30. data/examples/rspec_and_capybara/Gemfile +6 -0
  31. data/examples/rspec_and_capybara/README.txt +19 -0
  32. data/examples/rspec_and_capybara/Rakefile +4 -0
  33. data/examples/rspec_and_capybara/spec/google_search_spec.rb +15 -0
  34. data/examples/rspec_and_capybara/spec/pagemodels/google_results_page.rb +24 -0
  35. data/examples/rspec_and_capybara/spec/pagemodels/google_search_page.rb +15 -0
  36. data/examples/rspec_and_capybara/spec/spec_helper.rb +11 -0
  37. data/lib/page_models/base.rb +28 -0
  38. data/lib/page_models/configuration.rb +30 -0
  39. data/lib/page_models/core.rb +13 -0
  40. data/lib/page_models/errors.rb +10 -0
  41. data/lib/page_models/integration/capybara.rb +0 -0
  42. data/lib/page_models/integration/cucumber.rb +16 -0
  43. data/lib/page_models/integration/rails.rb +1 -0
  44. data/lib/page_models/integration/rspec.rb +19 -0
  45. data/lib/page_models/version.rb +3 -0
  46. data/lib/pagemodels.rb +1 -0
  47. data/pagemodels.gemspec +23 -0
  48. data/spec/page_models/base_spec.rb +58 -0
  49. data/spec/page_models/configuration_spec.rb +37 -0
  50. data/spec/spec_helper.rb +1 -0
  51. metadata +118 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in page-models.gemspec
4
+ gemspec
data/README.txt ADDED
@@ -0,0 +1,58 @@
1
+ Page Models move complex and copy-pasted code out of your acceptance tests and into easily managed Ruby classes with (optional) integration for Rails, Cucumber, and RSpec.
2
+
3
+
4
+ ~~~~~~~~
5
+ # env.rb
6
+ require 'pagemodels'
7
+
8
+ PageModels.configure do |config|
9
+ config.driver = :capybara
10
+ config.integrate :rspec
11
+ config.integrate :cucumber
12
+ config.integrate :rails
13
+ end
14
+
15
+
16
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
17
+ # my_cucumber_test.feature
18
+ Given I open the GitHub project page for the user "rickgrundy" and the repo "page-models"
19
+ When I look at the commit history
20
+ Then I should see at least 3 commits
21
+
22
+
23
+ ~~~~~~~~~~~~~~~~~~~~~~
24
+ # my_cucumber_steps.rb
25
+ When /I look at the commit history/ do
26
+ page_model.navigate_to_commits
27
+ end
28
+
29
+ Then /I should see at least (\d+) commits/ do |count|
30
+ page_model.verify_commit_count(count)
31
+ end
32
+
33
+
34
+ ~~~~~~~~~~~~~~~~~~~~~~
35
+ # GitHubProjectPage.rb
36
+ class GitHubProjectPage < PageModels::Base
37
+ def initialize(user, repo)
38
+ @user, @repo = user, repo
39
+ end
40
+
41
+ def url
42
+ "https://www.github.com/#{@user}/#{@repo}/"
43
+ end
44
+
45
+ def verify!
46
+ should have_content "#{@user} / #{@repo}"
47
+ should have_content "Source"
48
+ should have_content "Commits"
49
+ end
50
+
51
+ def navigate_to_commits
52
+ click_link "Commits"
53
+ end
54
+
55
+ def verify_commit_count(count)
56
+ all(".commit").should have_at_least(count).things
57
+ end
58
+ end
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => [:spec]
@@ -0,0 +1,4 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '3.0.7'
4
+
5
+ group :test do
6
+ gem 'cucumber-rails'
7
+ gem 'rspec', '>= 2.5.0'
8
+ gem 'capybara'
9
+ gem 'launchy'
10
+ gem 'pagemodels', :path => File.join(File.dirname(__FILE__), "..", "..")
11
+ end
@@ -0,0 +1,23 @@
1
+ This example demonstrates how to use page models to test a Rails app with Cucumber and RSpec, using Capybara/Rack-Test as a driver.
2
+
3
+ This example demonstrates how to use page models with RSpec to write acceptance tests for any website (in this case Google.com), using Capybara/Selenium/Firefox as a driver.
4
+
5
+ ~~~~~~~~~~
6
+
7
+ See features/support/env.rb for information about configuring PageModels to integrate with the various frameworks:
8
+
9
+ PageModels.configure do |config|
10
+ config.driver = :capybara
11
+ config.integrate :rails
12
+ config.integrate :cucumber
13
+ config.integrate :rspec
14
+ end
15
+
16
+ env.rb also loads all everything in the pagemodels directory. GoogleSearchPage and GoogleResultsPage provide examples of page models which override PageModels::Base.
17
+
18
+ ~~~~~~~~~~
19
+
20
+ RSpec integration exposes two convenience methods you may use in your specs:
21
+
22
+ open_page(page_model) - switches the current page model to the one provided and calls #open!
23
+ should_see_page(page_model) - switches the current page model and calls #verify!
@@ -0,0 +1,7 @@
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 File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ RailsAndCucumber::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,7 @@
1
+ class FinancialReportsController < ApplicationController
2
+ def show
3
+ @year = params[:year]
4
+ @txn_type = params[:txn_type]
5
+ @txns = Transaction.find_all(:year => @year, :type => @txn_type)
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ class Transaction
2
+ attr_accessor :type, :amount, :year
3
+
4
+ def self.truncate
5
+ @@all = []
6
+ end
7
+
8
+ def self.create(attrs)
9
+ txn = Transaction.new(attrs)
10
+ @@all << txn
11
+ txn
12
+ end
13
+
14
+ def self.find_all(attrs)
15
+ @@all.select do |txn|
16
+ attrs.all? { |k, v| txn.send(k) == v }
17
+ end
18
+ end
19
+
20
+ def initialize(attrs)
21
+ self.type = attrs[:type]
22
+ self.amount = attrs[:amount]
23
+ self.year = attrs[:year]
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ <h1>Acme Financial Report for <%= @year %></h1>
2
+
3
+ <% if @txns.empty? %>
4
+ <h2>There are no <%= @txn_type %> transactions for <%= @year %></h2>
5
+ <% else %>
6
+ <h2>All <%= @txn_type.titlecase %> Transactions</h2>
7
+
8
+ <table id="report">
9
+ <tr>
10
+ <th>Type</th>
11
+ <th>Amount</th>
12
+ </tr>
13
+ <% @txns.each do |txn| %>
14
+ <tr class="transaction">
15
+ <td class="type"><%= txn.type %></td>
16
+ <td class="amount"><%= txn.amount %></td>
17
+ </tr>
18
+ <% end %>
19
+ </table>
20
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Acme Financial Reporting</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "action_controller/railtie"
4
+
5
+ # If you have a Gemfile, require the gems listed there, including any gems
6
+ # you've limited to :test, :development, or :production.
7
+ Bundler.require(:default, Rails.env) if defined?(Bundler)
8
+
9
+ module RailsAndCucumber
10
+ class Application < Rails::Application
11
+
12
+ # Configure the default encoding used in templates for Ruby 1.9.
13
+ config.encoding = "utf-8"
14
+
15
+ # Configure sensitive parameters which will be filtered from the log file.
16
+ config.filter_parameters += [:password]
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,8 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
5
+ %>
6
+ default: <%= std_opts %> features
7
+ wip: --tags @wip:3 --wip features
8
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ RailsAndCucumber::Application.initialize!
@@ -0,0 +1,23 @@
1
+ RailsAndCucumber::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 webserver when you make code changes.
7
+ config.cache_classes = false
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.consider_all_requests_local = true
14
+ config.action_view.debug_rjs = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Print deprecation notices to the Rails logger
18
+ config.active_support.deprecation = :log
19
+
20
+ # Only use best-standards-support built into browsers
21
+ config.action_dispatch.best_standards_support = :builtin
22
+ end
23
+
@@ -0,0 +1,30 @@
1
+ RailsAndCucumber::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
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Raise exceptions instead of rendering exception templates
18
+ config.action_dispatch.show_exceptions = false
19
+
20
+ # Disable request forgery protection in test environment
21
+ config.action_controller.allow_forgery_protection = false
22
+
23
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
24
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
25
+ # like if you have constraints or database-specific column types
26
+ # config.active_record.schema_format = :sql
27
+
28
+ # Print deprecation notices to the stderr
29
+ config.active_support.deprecation = :stderr
30
+ end
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+ # Make sure the secret is at least 30 characters and all random,
6
+ # no regular words or you'll be exposed to dictionary attacks.
7
+ RailsAndCucumber::Application.config.secret_token = '223801ad784b8e3e5beea705d599a50bfd6efefaf64b367356d4b808b500cade554c7b2d3efa831dcc931bad3a0d15ed889652e42069b12726b7181f49c44dad'
@@ -0,0 +1,8 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ RailsAndCucumber::Application.config.session_store :cookie_store, :key => '_rails_and_cucumber_session'
4
+
5
+ # Use the database for sessions instead of the cookie-based default,
6
+ # which shouldn't be used to store highly confidential information
7
+ # (create the session table with "rails generate session_migration")
8
+ # RailsAndCucumber::Application.config.session_store :active_record_store
@@ -0,0 +1,3 @@
1
+ RailsAndCucumber::Application.routes.draw do
2
+ resource :financial_report
3
+ end
@@ -0,0 +1,29 @@
1
+ Feature: Viewing financial reports
2
+ As an Acme Financial Reporting accountant
3
+ I want to see reports for specific types of transaction
4
+ So that I know how much commission to pay my suppliers.
5
+
6
+ Background:
7
+ Given the following transactions:
8
+ | type | amount | year |
9
+ | visa | $100 | 2011 |
10
+ | cash | $50 | 2011 |
11
+ | visa | $30 | 1999 |
12
+ | visa | $80 | 2011 |
13
+
14
+ Scenario: Viewing visa transactions for 2011
15
+ When I open the financial report page for "visa" in "2011"
16
+ Then I should only see the following transactions:
17
+ | type | amount |
18
+ | visa | $100 |
19
+ | visa | $80 |
20
+
21
+ Scenario: Viewing cash transactions for 2011
22
+ When I open the financial report page for "cash" in "2011"
23
+ Then I should only see the following transactions:
24
+ | type | amount |
25
+ | cash | $50 |
26
+
27
+ Scenario: Viewing cash transactions for 1999
28
+ When I open the financial report page for "cash" in "1999"
29
+ Then I should not see any transactions
@@ -0,0 +1,29 @@
1
+ class FinancialReportPage < PageModels::Base
2
+ def initialize(txn_type, year)
3
+ @txn_type = txn_type.parameterize
4
+ @year = year
5
+ end
6
+
7
+ def url
8
+ financial_report_path(:txn_type => @txn_type, :year => @year)
9
+ end
10
+
11
+ def verify!
12
+ should have_content "Acme Financial Report for #{@year}"
13
+ end
14
+
15
+ def verify_transactions(txns)
16
+ rows = all("#report .transaction")
17
+ rows.should have(txns.size).things
18
+
19
+ txns.each_with_index do |txn, i|
20
+ rows[i].find(".type").should have_content txn["type"]
21
+ rows[i].find(".amount").should have_content txn["amount"]
22
+ end
23
+ end
24
+
25
+ def verify_no_transactions
26
+ should have_content "There are no #{@txn_type} transactions for #{@year}"
27
+ all("#report .transaction").should be_empty
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ Given /^the following transactions:$/ do |table|
2
+ Transaction.truncate
3
+ table.hashes.each do |hash|
4
+ Transaction.create(hash.symbolize_keys)
5
+ end
6
+ end
7
+
8
+ Then /^I should only see the following transactions:$/ do |table|
9
+ page_model.verify_transactions(table.hashes)
10
+ end
11
+
12
+ Then /^I should not see any transactions$/ do
13
+ page_model.verify_no_transactions
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'cucumber/rails'
2
+ Capybara.default_selector = :css
3
+ ActionController::Base.allow_rescue = false
4
+
5
+ require 'pagemodels'
6
+ Dir.glob(File.join(File.dirname(__FILE__), "pagemodels", "..", "**", "*.rb")).each { |f| require f }
7
+
8
+ PageModels.configure do |config|
9
+ config.driver = :capybara
10
+ config.integrate :rails
11
+ config.integrate :cucumber
12
+ config.integrate :rspec
13
+ end
@@ -0,0 +1,57 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+
7
+
8
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
9
+
10
+ vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
11
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
12
+
13
+ begin
14
+ require 'cucumber/rake/task'
15
+
16
+ namespace :cucumber do
17
+ Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
18
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
19
+ t.fork = true # You may get faster startup if you set this to false
20
+ t.profile = 'default'
21
+ end
22
+
23
+ Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
24
+ t.binary = vendored_cucumber_bin
25
+ t.fork = true # You may get faster startup if you set this to false
26
+ t.profile = 'wip'
27
+ end
28
+
29
+ Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
30
+ t.binary = vendored_cucumber_bin
31
+ t.fork = true # You may get faster startup if you set this to false
32
+ t.profile = 'rerun'
33
+ end
34
+
35
+ desc 'Run all features'
36
+ task :all => [:ok, :wip]
37
+ end
38
+ desc 'Alias for cucumber:ok'
39
+ task :cucumber => 'cucumber:ok'
40
+
41
+ task :default => :cucumber
42
+
43
+ task :features => :cucumber do
44
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
45
+ end
46
+
47
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
48
+ task 'db:test:prepare' do
49
+ end
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
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
4
+ if vendored_cucumber_bin
5
+ load File.expand_path(vendored_cucumber_bin)
6
+ else
7
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
8
+ require 'cucumber'
9
+ load Cucumber::BINARY
10
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rspec', '>= 2.5.0'
4
+ gem 'capybara'
5
+ gem 'launchy'
6
+ gem 'pagemodels', :path => File.join(File.dirname(__FILE__), "..", "..")
@@ -0,0 +1,19 @@
1
+ This example demonstrates how to use page models with RSpec to write acceptance tests for any website (in this case Google.com), using Capybara/Selenium/Firefox as a driver.
2
+
3
+ ~~~~~~~~~~
4
+
5
+ See spec/spec_helper.rb for information about configuring PageModels to integrate with the various frameworks:
6
+
7
+ PageModels.configure do |config|
8
+ config.driver = :capybara
9
+ config.integrate :rspec
10
+ end
11
+
12
+ spec_helper.rb also loads all everything in the pagemodels directory. GoogleSearchPage and GoogleResultsPage provide examples of page models which override PageModels::Base.
13
+
14
+ ~~~~~~~~~~
15
+
16
+ RSpec integration exposes two convenience methods you may use in your specs:
17
+
18
+ open_page(page_model) - switches the current page model to the one provided and calls #open!
19
+ should_see_page(page_model) - switches the current page model and calls #verify!
@@ -0,0 +1,4 @@
1
+ require 'rspec/core/rake_task'
2
+ RSpec::Core::RakeTask.new(:spec)
3
+
4
+ task :default => [:spec]
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "Searching Google" do
4
+ it "should show results for Ruby Page Models" do
5
+ open_page(GoogleSearchPage.new)
6
+ page_model.search_for("Ruby Page Models")
7
+
8
+ should_see_page(GoogleResultsPage.new("Ruby Page Models"))
9
+ page_model.verify_more_than_one_page_of_results
10
+ page_model.verify_special_results_option("Images")
11
+ page_model.verify_special_results_option("News")
12
+
13
+ page_model.verify_top_result("http://www.github.com/rickgrundy/pagemodels")
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ class GoogleResultsPage < PageModels::Base
2
+ def initialize(query)
3
+ @query = query
4
+ end
5
+
6
+ def verify!
7
+ should have_content @query
8
+ should have_content "More search tools"
9
+ end
10
+
11
+ def verify_more_than_one_page_of_results
12
+ all("table#nav a.fl").should have_at_least(2).things
13
+ end
14
+
15
+ def verify_special_results_option(option)
16
+ within("#leftnav") do
17
+ should have_content option
18
+ end
19
+ end
20
+
21
+ def verify_top_result(url)
22
+ find("#search cite:first").text.should == url
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ class GoogleSearchPage < PageModels::Base
2
+ def url
3
+ "http://www.google.com.au/"
4
+ end
5
+
6
+ def verify!
7
+ should have_content "About Google"
8
+ should_not have_content "More search tools"
9
+ end
10
+
11
+ def search_for(query)
12
+ fill_in "q", :with => query
13
+ click_button "Google Search"
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'capybara/rspec'
2
+ require 'pagemodels'
3
+
4
+ Dir.glob(File.join(File.dirname(__FILE__), "pagemodels", "**", "*.rb")).each { |f| require f }
5
+
6
+ Capybara.default_driver = :selenium
7
+
8
+ PageModels.configure do |config|
9
+ config.driver = :capybara
10
+ config.integrate :rspec
11
+ end
@@ -0,0 +1,28 @@
1
+ module PageModels
2
+ class Base
3
+ def open!
4
+ visit(url)
5
+ verify!
6
+ end
7
+
8
+ def method_missing(name, *args, &block)
9
+ config.driver.send(name, *args, &block)
10
+ rescue NoMethodError
11
+ super(name, *args, &block)
12
+ end
13
+
14
+ def url
15
+ raise ImplementationError.new(self, __method__)
16
+ end
17
+
18
+ def verify!
19
+ raise ImplementationError.new(self, __method__)
20
+ end
21
+
22
+ private
23
+
24
+ def config
25
+ PageModels::Configuration.instance
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'singleton'
2
+
3
+ module PageModels
4
+ class Configuration
5
+ include Singleton
6
+ attr_writer :driver
7
+
8
+ def initialize
9
+ @driver = :capybara
10
+ @frameworks = []
11
+ end
12
+
13
+ def integrate(framework)
14
+ @frameworks << framework
15
+ end
16
+
17
+ def integrate!
18
+ @frameworks.each { |framework| require "page_models/integration/#{framework}" }
19
+ end
20
+
21
+ def driver
22
+ case @driver
23
+ when :capybara
24
+ Capybara.current_session
25
+ else
26
+ raise ConfigurationError.new("No driver configured.")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ module PageModels
2
+ def self.configure
3
+ config = PageModels::Configuration.instance
4
+ yield(config)
5
+ config.integrate!
6
+ end
7
+
8
+ def self.create(page, args)
9
+ args = args.scan(/"([^"]+)"/).map(&:first)
10
+ page_model_class_name = page.gsub(/(?:^|[^\w])([a-z])/) { $1.upcase }
11
+ Kernel.const_get(page_model_class_name).new(*args)
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module PageModels
2
+ class ConfigurationError < StandardError
3
+ end
4
+
5
+ class ImplementationError < StandardError
6
+ def initialize(page_model, method)
7
+ super("#{page_model.class} must implement ##{method}.")
8
+ end
9
+ end
10
+ end
File without changes
@@ -0,0 +1,16 @@
1
+ Given /^I open the (.+ page)(.*)$/ do |page, args|
2
+ self.page_model = PageModels.create(page, args)
3
+ page_model.open!
4
+ end
5
+
6
+ Then /^I should see the (.+ page)(.*)$/ do |page, args|
7
+ self.page_model = PageModels.create(page, args)
8
+ page_model.verify!
9
+ end
10
+
11
+ module PageModels
12
+ module CucumberIntegration
13
+ attr_accessor :page_model
14
+ end
15
+ end
16
+ World(PageModels::CucumberIntegration)
@@ -0,0 +1 @@
1
+ PageModels::Base.send(:include, Rails.application.routes.url_helpers)
@@ -0,0 +1,19 @@
1
+ PageModels::Base.send(:include, RSpec::Matchers)
2
+
3
+ module PageModels
4
+ module RSpecIntegration
5
+ attr_accessor :page_model
6
+
7
+ def open_page(page_model)
8
+ self.page_model = page_model
9
+ page_model.open!
10
+ end
11
+
12
+ def should_see_page(page_model)
13
+ self.page_model = page_model
14
+ page_model.verify!
15
+ end
16
+ end
17
+ end
18
+
19
+ Object.send(:include, PageModels::RSpecIntegration)
@@ -0,0 +1,3 @@
1
+ module PageModels
2
+ VERSION = "0.1.0"
3
+ end
data/lib/pagemodels.rb ADDED
@@ -0,0 +1 @@
1
+ Dir.glob(File.join(File.dirname(__FILE__), "page_models", "*.rb")).each { |f| require f }
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "page_models/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pagemodels"
7
+ s.version = PageModels::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rick Grundy"]
10
+ s.email = ["rick@rickgrundy.com"]
11
+ s.homepage = "http://www.github.com/rickgrundy/pagemodels"
12
+ s.summary = "Page models for your browser driving acceptance tests with optional integration for RSpec, Cucumber, and Rails."
13
+ s.description = "See http://www.github.com/rickgrundy/pagemodels"
14
+
15
+ s.rubyforge_project = "pagemodels"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'rspec', '>= 2.5.0'
23
+ end
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "../../spec_helper")
2
+
3
+ describe PageModels::Base do
4
+ class UnimplementedPageModel < PageModels::Base
5
+ end
6
+
7
+ class TestPageModel < PageModels::Base
8
+ def url
9
+ "/test-page"
10
+ end
11
+
12
+ def verify!
13
+ true
14
+ end
15
+ end
16
+
17
+ describe "template methods which must be implemented by your page models" do
18
+ it "should raise an error if page models do not implement #url" do
19
+ lambda { UnimplementedPageModel.new.url }.should raise_error(PageModels::ImplementationError)
20
+ end
21
+
22
+ it "should raise an error if page models do not implement #verify!" do
23
+ lambda { UnimplementedPageModel.new.verify! }.should raise_error(PageModels::ImplementationError)
24
+ end
25
+ end
26
+
27
+ describe "delegating methods to the driver for less verbose page models" do
28
+ before(:each) do
29
+ @driver = Object.new
30
+ PageModels::Configuration.instance.stub(:driver).and_return(@driver)
31
+ @page_model = TestPageModel.new
32
+ end
33
+
34
+ it "should delegate a missing method to the driver" do
35
+ @driver.should_receive(:do_something_cool).with(:please)
36
+ @page_model.do_something_cool(:please)
37
+ end
38
+
39
+ it "should should not hide method missing errors if the method does not exist on the driver" do
40
+ lambda { @page_model.do_something_else }.should raise_error(NoMethodError, "undefined method `do_something_else' for #{@page_model.inspect}")
41
+ end
42
+ end
43
+
44
+ describe "opening a page" do
45
+ before(:each) do
46
+ @driver = Object.new
47
+ PageModels::Configuration.instance.stub(:driver).and_return(@driver)
48
+ @page_model = TestPageModel.new
49
+ end
50
+
51
+ it "should visit the page, then call verify" do
52
+ @page_model.should_receive(:visit).with("/test-page")
53
+ @page_model.should_receive(:verify!)
54
+ @page_model.open!
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "../../spec_helper")
2
+
3
+ module Capybara
4
+ def self.current_session
5
+ @session ||= Object.new
6
+ end
7
+ end
8
+
9
+ describe PageModels::Configuration do
10
+ before(:each) do
11
+ @config = PageModels::Configuration.instance
12
+ end
13
+
14
+ describe "providing a driver" do
15
+ it "should raise an error if no driver is configured" do
16
+ @config.driver = nil
17
+ lambda { @config.driver }.should raise_error(PageModels::ConfigurationError)
18
+ end
19
+
20
+ it "should provide a Capybara session" do
21
+ @config.driver = :capybara
22
+ @config.driver.should == Capybara.current_session
23
+ end
24
+ end
25
+
26
+ describe "integrating with frameworks" do
27
+ it "should require the appropriate integration files" do
28
+ @config.integrate :foo
29
+ @config.integrate :bar
30
+
31
+ @config.should_receive(:require).with("page_models/integration/foo")
32
+ @config.should_receive(:require).with("page_models/integration/bar")
33
+
34
+ @config.integrate!
35
+ end
36
+ end
37
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "..", "lib", "pagemodels")
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pagemodels
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Rick Grundy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-18 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 2.5.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ description: See http://www.github.com/rickgrundy/pagemodels
28
+ email:
29
+ - rick@rickgrundy.com
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - README.txt
40
+ - Rakefile
41
+ - examples/rails_and_cucumber/.gitignore
42
+ - examples/rails_and_cucumber/Gemfile
43
+ - examples/rails_and_cucumber/README.txt
44
+ - examples/rails_and_cucumber/Rakefile
45
+ - examples/rails_and_cucumber/app/controllers/application_controller.rb
46
+ - examples/rails_and_cucumber/app/controllers/financial_reports_controller.rb
47
+ - examples/rails_and_cucumber/app/models/transaction.rb
48
+ - examples/rails_and_cucumber/app/views/financial_reports/show.html.erb
49
+ - examples/rails_and_cucumber/app/views/layouts/application.html.erb
50
+ - examples/rails_and_cucumber/config/application.rb
51
+ - examples/rails_and_cucumber/config/boot.rb
52
+ - examples/rails_and_cucumber/config/cucumber.yml
53
+ - examples/rails_and_cucumber/config/environment.rb
54
+ - examples/rails_and_cucumber/config/environments/development.rb
55
+ - examples/rails_and_cucumber/config/environments/test.rb
56
+ - examples/rails_and_cucumber/config/initializers/secret_token.rb
57
+ - examples/rails_and_cucumber/config/initializers/session_store.rb
58
+ - examples/rails_and_cucumber/config/routes.rb
59
+ - examples/rails_and_cucumber/features/financial_reporting.feature
60
+ - examples/rails_and_cucumber/features/pagemodels/financial_report_page.rb
61
+ - examples/rails_and_cucumber/features/step_definitions/financial_reporting_steps.rb
62
+ - examples/rails_and_cucumber/features/support/env.rb
63
+ - examples/rails_and_cucumber/lib/tasks/cucumber.rake
64
+ - examples/rails_and_cucumber/script/cucumber
65
+ - examples/rails_and_cucumber/script/rails
66
+ - examples/rspec_and_capybara/Gemfile
67
+ - examples/rspec_and_capybara/README.txt
68
+ - examples/rspec_and_capybara/Rakefile
69
+ - examples/rspec_and_capybara/spec/google_search_spec.rb
70
+ - examples/rspec_and_capybara/spec/pagemodels/google_results_page.rb
71
+ - examples/rspec_and_capybara/spec/pagemodels/google_search_page.rb
72
+ - examples/rspec_and_capybara/spec/spec_helper.rb
73
+ - lib/page_models/base.rb
74
+ - lib/page_models/configuration.rb
75
+ - lib/page_models/core.rb
76
+ - lib/page_models/errors.rb
77
+ - lib/page_models/integration/capybara.rb
78
+ - lib/page_models/integration/cucumber.rb
79
+ - lib/page_models/integration/rails.rb
80
+ - lib/page_models/integration/rspec.rb
81
+ - lib/page_models/version.rb
82
+ - lib/pagemodels.rb
83
+ - pagemodels.gemspec
84
+ - spec/page_models/base_spec.rb
85
+ - spec/page_models/configuration_spec.rb
86
+ - spec/spec_helper.rb
87
+ has_rdoc: true
88
+ homepage: http://www.github.com/rickgrundy/pagemodels
89
+ licenses: []
90
+
91
+ post_install_message:
92
+ rdoc_options: []
93
+
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: "0"
108
+ requirements: []
109
+
110
+ rubyforge_project: pagemodels
111
+ rubygems_version: 1.5.0
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Page models for your browser driving acceptance tests with optional integration for RSpec, Cucumber, and Rails.
115
+ test_files:
116
+ - spec/page_models/base_spec.rb
117
+ - spec/page_models/configuration_spec.rb
118
+ - spec/spec_helper.rb