gizmo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Luke Cunningham
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.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ Gizmo
2
+ ============
3
+
4
+ In homage to its humble beginnings as our 'gremlin' testing submodule.<br />
5
+ We were entrusted with it and asked to follow 3 simple rules...
6
+
7
+ * "Don't get it wet"
8
+ * "Keep it away from bright lights....especially sunlight"
9
+ * "Don't ever feed it after midnight"
10
+
11
+ We didn't listen, and it got nasty...<br />
12
+ So we've gone back to the drawing board and come up with a friendlier, cuddlier testing helper.
13
+
14
+ **Gizmo** is a simple page model testing framework used and sponsored by [realestate.com.au](http://www.realestate.com.au). The aim of the project is to DRY up testing assertions by abstracting code that defines your page, resulting in a consistent, easy to maintain test suite. The code is maintained by Contributors from REA, and largely based on concepts brought to REA by [Mark Ryall](http://github.com/markryall) and other [thoughtworkers](http://thoughtworks.com.au/)
15
+
16
+ **this project is a work in progress, and not really ready to be used for its intended purpose!**
17
+
18
+
19
+ ## Usage ##
20
+
21
+ see [this gist](http://gist.github.com/339570) for some code examples
22
+
23
+ **for cucumber:**
24
+
25
+ * write your features just like you usually would
26
+ * require 'gizmo' and add the Gizmo::Helpers to the World
27
+ * generate your page mixins and fill them out with your page selectors
28
+ * use the page model when writing your steps
29
+
30
+
31
+ **for rspec:**
32
+
33
+ * require 'gizmo' in your spec_helper and include Gizmo::Helpers methods
34
+ * generate your page mixins and fill them out with your page selectors
35
+ * use the page model when writing your specs
36
+
37
+
38
+ ## Contributing ##
39
+
40
+ * Fork the project.
41
+ * Make your feature addition or bug fix.
42
+ * Make sure you write tests. Pull requests will not be accepted unless they have complete coverage.
43
+ * Commit, do not mess with rakefile, version, or history.
44
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
45
+ * Send me a pull request.
46
+
47
+ ## Sponsored by ##
48
+ [realestate.com.au](http://www.realestate.com.au)
data/Rakefile ADDED
@@ -0,0 +1,87 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "gizmo"
8
+ gem.summary = %Q{simple page model testing framework}
9
+ gem.description = %Q{gizmo is a simple page model testing framework used and sponsored by 'realestate.com.au'. The aim of the project is to DRY up your testing assertions by abstracting code that defines your page resulting in a consistent, easy to maintain test suit}
10
+ gem.email = "luke@icaruswings.com"
11
+ gem.homepage = "http://github.com/icaruswings/gizmo"
12
+ gem.authors = ["Luke Cunningham"]
13
+ gem.add_development_dependency "rspec", ">= 1.3.0"
14
+ gem.add_development_dependency "cucumber", ">= 0.6.3"
15
+ gem.add_development_dependency "webrat", ">= 0.7.0"
16
+ gem.add_development_dependency "capybara", ">= 0.3.5"
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ gem.add_dependency "nokogiri", ">= 1.4.1"
19
+ gem.add_dependency "activesupport", ">= 2.3.5"
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ spec.rcov_opts = ['--failure-threshold', 100, '--exclude', 'features']
37
+ end
38
+
39
+ task :spec => :check_dependencies
40
+
41
+ begin
42
+ require 'cucumber/rake/task'
43
+ Cucumber::Rake::Task.new(:features)
44
+
45
+ task :features => :check_dependencies
46
+ rescue LoadError
47
+ task :features do
48
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
49
+ end
50
+ end
51
+
52
+ begin
53
+ require 'reek/adapters/rake_task'
54
+ Reek::RakeTask.new do |t|
55
+ t.fail_on_error = true
56
+ t.verbose = false
57
+ t.source_files = 'lib/**/*.rb'
58
+ end
59
+ rescue LoadError
60
+ task :reek do
61
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
62
+ end
63
+ end
64
+
65
+ begin
66
+ require 'roodi'
67
+ require 'roodi_task'
68
+ RoodiTask.new do |t|
69
+ t.verbose = false
70
+ end
71
+ rescue LoadError
72
+ task :roodi do
73
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
74
+ end
75
+ end
76
+
77
+ task :default => :spec
78
+
79
+ require 'rake/rdoctask'
80
+ Rake::RDocTask.new do |rdoc|
81
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
82
+
83
+ rdoc.rdoc_dir = 'rdoc'
84
+ rdoc.title = "gizmo #{version}"
85
+ rdoc.rdoc_files.include('README*')
86
+ rdoc.rdoc_files.include('lib/**/*.rb')
87
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/gizmo ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require 'optparse'
5
+ require 'active_support'
6
+
7
+ $LOAD_PATH << File.dirname(__FILE__) + '/../lib'
8
+ require 'gizmo'
9
+
10
+ @current_mixin = nil
11
+
12
+ def puts_list methods
13
+ return puts "[]" if methods.empty?
14
+ puts methods.sort.join(', ')
15
+ end
16
+
17
+ opts = OptionParser.new do |opts|
18
+
19
+ opts.on("-v", "--version", "what's the frequency kenneth?") do
20
+ puts "gizmo version: 0.0.0"
21
+ end
22
+
23
+ opts.on("-g", "--generate-mixin [NAME]", "generate a new page mixin") do |mixin_name|
24
+ File.open("#{Gizmo::Config.mixin_path}/page_with_#{mixin_name}.rb", "w") do |file|
25
+ content = <<-EOS
26
+ module PageWith#{mixin_name.camelize}
27
+ # def valid
28
+ # has_selector?('my-container')
29
+ # end
30
+ end
31
+ EOS
32
+ file.write(content.strip)
33
+ end
34
+ end
35
+
36
+ opts.on("-p", "--with-page [NAME]") do |mixin_name|
37
+ Gizmo.load_mixins! File.join(Dir.pwd, Gizmo::Config.mixin_path)
38
+ mixin = Object.const_get("PageWith" + mixin_name.camelize)
39
+ @current_mixin = { :name => mixin_name, :obj => Gizmo::Page.new({}, '', {}).extend(mixin) }
40
+ end
41
+
42
+ opts.on('-m', '--list-methods', 'list all the methods for a mixin') do
43
+ puts "---- methods for #{@current_mixin[:name]} ----"
44
+ puts_list @current_mixin[:obj].methods
45
+ end
46
+
47
+ opts.on('-f', '--filter-methods [QUERY]', 'filter methods for a mixin') do |query|
48
+ puts "---- methods for #{@current_mixin[:name]} matching #{query} ----"
49
+ puts_list @current_mixin[:obj].methods.select { |m| m =~ /#{query}/ }
50
+ end
51
+
52
+ end
53
+
54
+
55
+ if ARGV.size == 0
56
+ puts "DRY up your acceptance tests. \ntype --help for a list of commands"
57
+ exit 1
58
+ end
59
+
60
+ opts.parse!
61
+
62
+ @current_mixin = nil
@@ -0,0 +1,12 @@
1
+ Feature:
2
+ As a behaviour driven developer
3
+ In order to have a DRY, elegant and maintainable test suite
4
+ I want 'gizmo' to do it's funky thing
5
+
6
+ Scenario: A scenario performs a github search
7
+ Given the scenario is on the github homepage
8
+ When the scenario enters "gizmo" into the search box
9
+ And the scenario clicks the magnifying glass icon
10
+ And the scenario clicks on the "icaruswings / gizmo" link
11
+ Then the scenario is on the "gizmo" github repository details page
12
+ And the scenario is on a github repository details page which belongs to "icaruswings"
@@ -0,0 +1,37 @@
1
+ Given /^the scenario is on the github homepage$/ do
2
+ visit "http://github.com"
3
+ end
4
+
5
+ When /^the scenario enters "([^\"]*)" into the search box$/ do |text|
6
+ on_page_with :github_search do |page|
7
+ fill_in page.search_form.input.attr('name').value, :with => text
8
+ end
9
+ end
10
+
11
+ When /^the scenario clicks the magnifying glass icon$/ do
12
+ on_page_with :github_search do |page|
13
+ click page.search_form.submit.attr('alt').value
14
+ end
15
+ end
16
+
17
+ When /^the scenario clicks on the "([^\"]*)" link$/ do |text|
18
+ click_link text
19
+ end
20
+
21
+ Then /^the scenario is on a github repository details page$/ do
22
+ on_page_with :github_repo_details do |page|
23
+ page.should be_valid
24
+ end
25
+ end
26
+
27
+ Then /^the scenario is on the "([^\"]*)" github repository details page$/ do |repo_name|
28
+ on_page_with :github_repo_details do |page|
29
+ page.repo_details.name == repo_name
30
+ end
31
+ end
32
+
33
+ Then /^the scenario is on a github repository details page which belongs to "([^\"]*)"$/ do |author|
34
+ on_page_with :github_repo_details do |page|
35
+ page.repo_details.author == author
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+ # $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+
3
+ require 'spec/expectations'
4
+
5
+ #CAPYBARA
6
+ require 'capybara/cucumber'
7
+ require 'capybara/session'
8
+ require 'features/support/patches/capybara'
9
+ Capybara.default_driver = :selenium
10
+ Capybara.run_server = false
11
+
12
+ #gizmo!!!
13
+ require 'gizmo'
14
+ World(Gizmo::Helpers)
15
+
16
+ Gizmo.configure do |config|
17
+ config.mixin_dir = File.dirname(__FILE__) + '/features/support/pages'
18
+ end
@@ -0,0 +1,14 @@
1
+ module PageWithGithubRepoDetails
2
+
3
+ def valid?
4
+ has_selector?("div.repohead")
5
+ end
6
+
7
+ def repo_details
8
+ OpenStruct do |repo_details|
9
+ repo_details.name = @document.css("h1>strong a").inner_text
10
+ repo_details.author = @document.css("h1>a").inner_text
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,16 @@
1
+ module PageWithGithubSearch
2
+
3
+ def valid?
4
+ has_selector?("div.search")
5
+ end
6
+
7
+ def search_form
8
+ OpenStruct do |form|
9
+ form.container = @document.css("div.search")
10
+ form.element = container = form.container.css("form")
11
+ form.input = container.css("input[name=q]")
12
+ form.submit = container.css("input[alt=search]")
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,43 @@
1
+ module PageWithGithubSearchResults
2
+
3
+ def valid?
4
+ has_selector?('div#code_search_results')
5
+ end
6
+
7
+
8
+ def search_results
9
+ OpenStruct do |results|
10
+ results.repositories = build_repositories
11
+ end
12
+ end
13
+
14
+
15
+ private
16
+
17
+ def build_repositories
18
+ OpenStruct do |repos|
19
+ container = find_results_container "Repositories"
20
+ repos.heading = container.css('div.header')
21
+ repos.results = container.css('div.result').map { |result| build_repository_result result }
22
+ end
23
+ end
24
+
25
+ def build_repository_result result
26
+ OpenStruct do |repo_result|
27
+ repo_result.title = result.css('h2.title')
28
+ repo_result.link = repo_result.title.css('a')
29
+ link_parts = repo_result.link.inner_text.split('/')
30
+ repo_result.name = link_parts[1].strip
31
+ repo_result.author = link_parts[0].strip
32
+ end
33
+ end
34
+
35
+ def find_results_container heading_text
36
+ all_headings = @document.css('div.header')
37
+ header = all_headings.find do |heading_element|
38
+ heading_element.css('div.title').inner_text =~ /#{heading_text} \((.+)\)/
39
+ end
40
+ header.parent unless header.nil?
41
+ end
42
+
43
+ end
@@ -0,0 +1,44 @@
1
+ if Object.const_defined? :Capybara
2
+
3
+ module Capybara
4
+ alias :response :page
5
+ end
6
+
7
+ class Capybara::Driver::Selenium < Capybara::Driver::Base
8
+ class Node < Capybara::Node
9
+
10
+ def is_radio?
11
+ tag_name == 'input' and type == 'radio'
12
+ end
13
+
14
+ def is_checkbox?
15
+ tag_name == 'input' and type == 'checkbox'
16
+ end
17
+
18
+ def is_text_field?
19
+ tag_name == 'textarea' or (tag_name == 'input' and %w(text password hidden file).include?(type))
20
+ end
21
+
22
+ def radio_input
23
+ node.select
24
+ end
25
+
26
+ def checkbox_input
27
+ node.click
28
+ end
29
+
30
+ def clear_and_send_keys value
31
+ node.clear
32
+ node.send_keys(value.to_s)
33
+ end
34
+
35
+ def set(value)
36
+ return clear_and_send_keys(value) if is_text_field?
37
+ return radio_input if is_radio?
38
+ return checkbox_input if is_checkbox?
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ end
data/lib/gizmo.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'nokogiri'
4
+
5
+ $LOAD_PATH << File.dirname(__FILE__)
6
+
7
+ module Gizmo
8
+
9
+ autoload :Page, "gizmo/page"
10
+ autoload :Helpers, "gizmo/helpers"
11
+ autoload :Generate, "gizmo/generate"
12
+
13
+ GizmoError = Class.new(StandardError)
14
+ MixinNotValidError = Class.new(GizmoError)
15
+ MixinNotFoundError = Class.new(GizmoError)
16
+ NilResponseError = Class.new(GizmoError)
17
+
18
+ end
19
+ require "gizmo/configuration"
20
+ require "gizmo/extras"
@@ -0,0 +1,31 @@
1
+ require 'pathname'
2
+
3
+ module Gizmo
4
+
5
+ # Configures Gizmo. If this is not done, Gizmo will use all defaults.
6
+ def self.configure(configuration = Gizmo.configuration)
7
+ yield configuration if block_given?
8
+ @@configuration = configuration
9
+ end
10
+
11
+ def self.configuration
12
+ @@configuration ||= Gizmo::Configuration.new
13
+ end
14
+
15
+ # Gizmo can be configured using the Gizmo.configure method. For example:
16
+ #
17
+ # Gizmo.configure do |config|
18
+ # config.mixin_dir = File.dirname(__FILE__) + '/features/support/pages'
19
+ # end
20
+ class Configuration
21
+
22
+ # where to load mixin files from
23
+ attr_accessor :mixin_dir
24
+
25
+ def initialize
26
+ self.mixin_dir = Pathname.new(Dir.pwd).join("features/support/pages")
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,6 @@
1
+ # make OpenStruct yield to a block.
2
+ def OpenStruct
3
+ open_struct = OpenStruct.new
4
+ yield open_struct if block_given?
5
+ open_struct
6
+ end
@@ -0,0 +1,32 @@
1
+ module Gizmo
2
+
3
+ module Helpers
4
+
5
+ def on_page &block
6
+ raise NilResponseError, "Doh! response object is nil. This generally means your scenario has not yet visited a page!" if response.nil?
7
+ raise ArgumentError, 'You must supply a block argument' unless block.is_a? Proc
8
+ yield Page.new(self, response.body, current_url)
9
+ end
10
+
11
+ def on_page_with *module_names
12
+ raise ArgumentError, 'You must supply at least one mixin' if module_names.empty?
13
+ on_page do |page|
14
+ module_names.each do |module_name|
15
+ raise ArgumentError, 'module_name must be a symbol' unless module_name.is_a?(Symbol)
16
+ const_name = "PageWith#{module_name.to_s.camelize}"
17
+ begin
18
+ require "#{Gizmo.configuration.mixin_dir}/page_with_#{module_name}.rb" unless Object.const_defined?(const_name)
19
+ rescue LoadError
20
+ raise MixinNotFoundError, "Expected a page mixin file at #{Gizmo.configuration.mixin_dir}/page_with_#{module_name}.rb generate one with gizmo -g #{module_name}"
21
+ end
22
+ page.extend(Object.const_get(const_name))
23
+ raise MixinNotValidError, "Page did not have #{module_name} at #{page.url}" unless page.valid?
24
+ page.mixins << module_name
25
+ end
26
+ yield page if block_given?
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
data/lib/gizmo/page.rb ADDED
@@ -0,0 +1,30 @@
1
+ module Gizmo
2
+
3
+ class Page
4
+
5
+ attr_reader :mixins, :url, :document
6
+
7
+ def initialize driver, content, url
8
+ @mixins = []
9
+ @browser = driver
10
+ @document = Nokogiri::HTML(content)
11
+ @url = url
12
+ end
13
+
14
+ # Pages are valid by default -
15
+ # specific mixins should change this behaviour
16
+ # to require certain elements on the page
17
+ # then you will get an error message saying "Page did not have mixin #{name}"
18
+ #eg.
19
+ # def valid?
20
+ # has_selector('some_element_selector')
21
+ # end
22
+ def valid?; true; end
23
+
24
+ def has_selector? css_selector
25
+ @document.css(css_selector).length > 0
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ # Dir[File.dirname(__FILE__) + '/../features/support/pages/*'].each do |path|
4
+ # require path if path =~ /page_with.+\.rb$/
5
+ # end
6
+
7
+ require 'capybara'
8
+ require 'capybara/dsl'
9
+ require File.expand_path(File.dirname(__FILE__) + '/../features/support/patches/capybara')
10
+
11
+ Capybara.default_driver = :selenium
12
+ Capybara.run_server = false
13
+ Spec::Runner.configure do |config|
14
+ config.include Capybara
15
+ end
16
+
17
+
18
+ describe "Github" do
19
+
20
+ before do
21
+ Gizmo.configure do |config|
22
+ config.mixin_dir = File.join(File.dirname(__FILE__), '../features/support/pages/')
23
+ end
24
+ end
25
+
26
+ describe "Home Page Search" do
27
+
28
+ before(:all) { visit 'http://github.com' }
29
+
30
+ it "should have a text input which accepts a search query" do
31
+ on_page_with :github_search do |page|
32
+ fill_in page.search_form.input.attr('name').value, :with => 'gizmo'
33
+ end
34
+ end
35
+
36
+ it "should perform a search when clicking the magnifying glass" do
37
+ on_page_with :github_search do |page|
38
+ click page.search_form.submit.attr('alt').value
39
+ end
40
+ end
41
+
42
+ it "should redirect to the search results page with gizmo as the first result" do
43
+ on_page_with :github_search_results do |page|
44
+ page.search_results.repositories.results.first.name.should == 'gizmo'
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ describe "Repo Details" do
51
+
52
+ before(:all) { visit 'http://github.com/icaruswings/gizmo' }
53
+
54
+ it "should have the expected repository name" do
55
+ on_page_with :github_repo_details do |page|
56
+ page.repo_details.name == 'gizmo'
57
+ end
58
+ end
59
+
60
+ it "should have the expected repository author" do
61
+ on_page_with :github_repo_details do |page|
62
+ page.repo_details.author == 'icaruswings'
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Gizmo" do
4
+
5
+ describe "Configuration" do
6
+
7
+ it "should have a mixin_dir reader" do
8
+ Gizmo.configuration.should respond_to(:mixin_dir)
9
+ end
10
+
11
+ it "should have a mixin_dir writer" do
12
+ Gizmo.configuration.should respond_to(:mixin_dir=)
13
+ end
14
+
15
+ it "should be configurable with a block" do
16
+ Gizmo.configure do |config|
17
+ config.mixin_dir = 'blah'
18
+ end
19
+
20
+ config = Gizmo.configuration
21
+ config.mixin_dir.should == 'blah'
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Gizmo" do
4
+
5
+ describe "Extras" do
6
+
7
+ it "should provide an override for OpenStruct to make it yield to a block" do
8
+ OpenStruct { |o| o.should be_an OpenStruct }
9
+ end
10
+
11
+ it "should return an OpenStruct if not given a block" do
12
+ send(:OpenStruct).should be_an OpenStruct
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,104 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Gizmo" do
4
+
5
+ describe "Helpers" do
6
+
7
+ before do
8
+ def response
9
+ mock_response = <<-eos
10
+ <html>
11
+ <head>
12
+ <title>my awesome web page</title>
13
+ </head>
14
+ <body>
15
+ <p class="one_of_these">paragraph one</p>
16
+ <p class="two_of_these">paragraph two</p>
17
+ <p class="two_of_these">paragraph three</p>
18
+ </body>
19
+ </html>
20
+ eos
21
+ @response ||= mock('response', :body => mock_response)
22
+ end
23
+
24
+ def current_url
25
+ 'http://www.example.com'
26
+ end
27
+ end
28
+
29
+ it "should provide a method :on_page" do
30
+ respond_to?(:on_page).should be_true
31
+ end
32
+
33
+ it "should provide a method :on_page_with" do
34
+ respond_to?(:on_page_with).should be_true
35
+ end
36
+
37
+ describe "#on_page" do
38
+ it "should raise an error if no block given" do
39
+ lambda { on_page }.should raise_error(ArgumentError, "You must supply a block argument")
40
+ end
41
+
42
+ it "should not raise an error if given a block" do
43
+ lambda { on_page { |page| return page } }.should_not raise_error(ArgumentError, "You must supply a block argument")
44
+ end
45
+
46
+ it "should yield a page object" do
47
+ on_page { |page| page.should be_a Gizmo::Page }
48
+ end
49
+
50
+ it "should raise an error if the response object is nil" do
51
+ response.stub!(:nil?).and_return(true)
52
+ lambda { on_page { |page| page } }.should raise_error(Gizmo::NilResponseError, "Doh! response object is nil. This generally means your scenario has not yet visited a page!")
53
+ end
54
+
55
+ end
56
+
57
+
58
+ describe "#on_page_with" do
59
+ it "should raise an error if one or more module_names are given" do
60
+ lambda { on_page_with }.should raise_error(ArgumentError, "You must supply at least one mixin")
61
+ end
62
+
63
+ it "should raise an ArgumentError if module_name is not a symbol" do
64
+ lambda { on_page_with 'my_module_name' }.should raise_error(ArgumentError, "module_name must be a symbol")
65
+ end
66
+
67
+ it "should not raise an error if module_name is a symbol" do
68
+ lambda { on_page_with :my_mixin }.should_not raise_error
69
+ end
70
+
71
+ it "should not raise ArgumentError if multiple module_names are given" do
72
+ lambda { on_page_with :my_mixin, :my_other_mixin }.should_not raise_error(ArgumentError, "module_name must be a symbol")
73
+ end
74
+
75
+ it "should raise Gizmo::MixinNotValidError if the mixin is not valid" do
76
+ lambda { on_page_with :my_invalid_mixin }.should raise_error(Gizmo::MixinNotValidError, "Page did not have my_invalid_mixin at http://www.example.com")
77
+ end
78
+
79
+ it "should raise Gizmo::MixinNotFoundError if the mixin file cannot be loaded from the mixin_path" do
80
+ lambda { on_page_with :my_non_existent_mixin }.should raise_error(Gizmo::MixinNotFoundError, "Expected a page mixin file at /Users/luke_cunningham/projects/icaruswings/gizmo/spec/pages/page_with_my_non_existent_mixin.rb generate one with gizmo -g my_non_existent_mixin")
81
+ end
82
+
83
+ it "should yield a page object to a block if supplied" do
84
+ on_page_with(:my_mixin) { |page| page.should_not be_nil }
85
+ end
86
+
87
+ it "should yield a page object to a block" do
88
+ on_page_with(:my_mixin) { |page| page.should be_a Gizmo::Page }
89
+ end
90
+
91
+ it "should return a page object which has been extended to include the mixin functionality" do
92
+ on_page_with(:my_mixin) do |page|
93
+ page.should respond_to :my_method
94
+ end
95
+ end
96
+
97
+ it "should add the mixin name to the Page's mixin instance attribute" do
98
+ on_page_with(:my_mixin, :my_other_mixin) do |page|
99
+ [:my_mixin, :my_other_mixin].each { |mixin| page.mixins.should include mixin }
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,114 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Gizmo" do
4
+
5
+ describe "Page" do
6
+
7
+ before do
8
+ def response
9
+ mock_response = <<-eos
10
+ <html>
11
+ <head>
12
+ <title>my awesome web page</title>
13
+ </head>
14
+ <body>
15
+ <p class="one_of_these">paragraph one</p>
16
+ <p class="two_of_these">paragraph two</p>
17
+ <p class="two_of_these">paragraph three</p>
18
+ </body>
19
+ </html>
20
+ eos
21
+ @response ||= mock('response', :body => mock_response)
22
+ end
23
+
24
+ def current_url
25
+ 'http://www.example.com'
26
+ end
27
+
28
+ @page = Gizmo::Page.new(self, response.body, current_url)
29
+ end
30
+
31
+ describe "attributes and accessors" do
32
+
33
+ it "should have an instance variable @mixins" do
34
+ @page.instance_variable_get(:@mixins).should_not be_nil
35
+ end
36
+
37
+ it "should have an instance variable @document" do
38
+ @page.instance_variable_get(:@document).should_not be_nil
39
+ end
40
+
41
+ it "should have an instance variable @url" do
42
+ @page.instance_variable_get(:@url).should_not be_nil
43
+ end
44
+
45
+ describe "@document" do
46
+ it "should be a Nokogiri::HTML document" do
47
+ @page.instance_variable_get(:@document).should be_a Nokogiri::HTML::Document
48
+ end
49
+ end
50
+
51
+ describe "@url" do
52
+ it "should return the expected string" do
53
+ @page.instance_variable_get(:@url).should == "http://www.example.com"
54
+ end
55
+ end
56
+
57
+ describe "@mixins" do
58
+ it "should be accessible with .mixins" do
59
+ @page.mixins.should equal @page.instance_variable_get(:@mixins)
60
+ end
61
+
62
+ it "should return an array" do
63
+ @page.mixins.should be_an(Array)
64
+ end
65
+
66
+ it "should be writable using instance_variable_set" do
67
+ mixins = @page.mixins << :new_mixin
68
+ @page.instance_variable_set :@mixins, mixins
69
+ @page.mixins.should include :new_mixin
70
+ end
71
+ end
72
+
73
+ it "should have an attribute reader for @mixins" do
74
+ @page.should respond_to(:mixins)
75
+ end
76
+
77
+ it "should not have an attribute writer for @mixins" do
78
+ @page.should_not respond_to(:mixins=)
79
+ end
80
+
81
+ it "should have an attribute reader for @url" do
82
+ @page.should respond_to(:url)
83
+ end
84
+
85
+ it "should not have an attribute writer for @url" do
86
+ @page.should_not respond_to(:url=)
87
+ end
88
+
89
+ it "should have attribute reader for @document" do
90
+ @page.should respond_to(:document)
91
+ end
92
+
93
+ it "should have attribute writer for @document" do
94
+ @page.should_not respond_to(:document=)
95
+ end
96
+
97
+ end
98
+
99
+ describe "#has_selector?" do
100
+
101
+ it "should return true if @document contains one or more elements matching the selector" do
102
+ @page.has_selector?('p.one_of_these').should be_true
103
+ @page.has_selector?('p.two_of_these').should be_true
104
+ end
105
+
106
+ it "should return false if @document does not contain one or more elements matching the selector" do
107
+ @page.has_selector?('p.does_not_exist').should be_false
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,2 @@
1
+ module PageWithTestMixinStuff
2
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --reverse
3
+ --backtrace
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'gizmo'
3
+
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ begin require 'redgreen' unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
8
+
9
+ Spec::Runner.configure do |config|
10
+ include Gizmo::Helpers
11
+
12
+ config.before do
13
+ Gizmo.configure do |config|
14
+ config.mixin_dir = File.dirname(__FILE__) + '/pages'
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ module PageWithMyOpenstruct
21
+ def my_openstruct; OpenStruct; end
22
+ end
23
+
24
+ module PageWithMyMixin
25
+ def my_method; nil; end
26
+ end
27
+
28
+ module PageWithMyOtherMixin
29
+ end
30
+
31
+ module PageWithMyInvalidMixin
32
+ def valid?; false; end
33
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gizmo
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Luke Cunningham
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-30 00:00:00 +11:00
18
+ default_executable: gizmo
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 3
30
+ - 0
31
+ version: 1.3.0
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: cucumber
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 6
44
+ - 3
45
+ version: 0.6.3
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: webrat
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ - 7
58
+ - 0
59
+ version: 0.7.0
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: capybara
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ - 3
72
+ - 5
73
+ version: 0.3.5
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: nokogiri
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 4
86
+ - 1
87
+ version: 1.4.1
88
+ type: :runtime
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: activesupport
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 2
99
+ - 3
100
+ - 5
101
+ version: 2.3.5
102
+ type: :runtime
103
+ version_requirements: *id006
104
+ description: gizmo is a simple page model testing framework used and sponsored by 'realestate.com.au'. The aim of the project is to DRY up your testing assertions by abstracting code that defines your page resulting in a consistent, easy to maintain test suit
105
+ email: luke@icaruswings.com
106
+ executables:
107
+ - gizmo
108
+ extensions: []
109
+
110
+ extra_rdoc_files:
111
+ - LICENSE
112
+ - README.md
113
+ files:
114
+ - .document
115
+ - .gitignore
116
+ - LICENSE
117
+ - README.md
118
+ - Rakefile
119
+ - VERSION
120
+ - bin/gizmo
121
+ - features/gizmo.feature
122
+ - features/step_definitions/gizmo_steps.rb
123
+ - features/support/env.rb
124
+ - features/support/pages/page_with_github_repo_details.rb
125
+ - features/support/pages/page_with_github_search.rb
126
+ - features/support/pages/page_with_github_search_results.rb
127
+ - features/support/patches/capybara.rb
128
+ - lib/gizmo.rb
129
+ - lib/gizmo/configuration.rb
130
+ - lib/gizmo/extras.rb
131
+ - lib/gizmo/helpers.rb
132
+ - lib/gizmo/page.rb
133
+ - spec/github_site_example_spec.rb
134
+ - spec/gizmo/configuration_spec.rb
135
+ - spec/gizmo/extras_spec.rb
136
+ - spec/gizmo/helpers_spec.rb
137
+ - spec/gizmo/page_spec.rb
138
+ - spec/pages/page_with_test_mixin_stuff.rb
139
+ - spec/spec.opts
140
+ - spec/spec_helper.rb
141
+ has_rdoc: true
142
+ homepage: http://github.com/icaruswings/gizmo
143
+ licenses: []
144
+
145
+ post_install_message:
146
+ rdoc_options:
147
+ - --charset=UTF-8
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ segments:
155
+ - 0
156
+ version: "0"
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ segments:
162
+ - 0
163
+ version: "0"
164
+ requirements: []
165
+
166
+ rubyforge_project:
167
+ rubygems_version: 1.3.6
168
+ signing_key:
169
+ specification_version: 3
170
+ summary: simple page model testing framework
171
+ test_files:
172
+ - spec/github_site_example_spec.rb
173
+ - spec/gizmo/configuration_spec.rb
174
+ - spec/gizmo/extras_spec.rb
175
+ - spec/gizmo/helpers_spec.rb
176
+ - spec/gizmo/page_spec.rb
177
+ - spec/pages/page_with_test_mixin_stuff.rb
178
+ - spec/spec_helper.rb