gizmo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.md +48 -0
- data/Rakefile +87 -0
- data/VERSION +1 -0
- data/bin/gizmo +62 -0
- data/features/gizmo.feature +12 -0
- data/features/step_definitions/gizmo_steps.rb +37 -0
- data/features/support/env.rb +18 -0
- data/features/support/pages/page_with_github_repo_details.rb +14 -0
- data/features/support/pages/page_with_github_search.rb +16 -0
- data/features/support/pages/page_with_github_search_results.rb +43 -0
- data/features/support/patches/capybara.rb +44 -0
- data/lib/gizmo.rb +20 -0
- data/lib/gizmo/configuration.rb +31 -0
- data/lib/gizmo/extras.rb +6 -0
- data/lib/gizmo/helpers.rb +32 -0
- data/lib/gizmo/page.rb +30 -0
- data/spec/github_site_example_spec.rb +68 -0
- data/spec/gizmo/configuration_spec.rb +26 -0
- data/spec/gizmo/extras_spec.rb +17 -0
- data/spec/gizmo/helpers_spec.rb +104 -0
- data/spec/gizmo/page_spec.rb +114 -0
- data/spec/pages/page_with_test_mixin_stuff.rb +2 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +33 -0
- metadata +178 -0
data/.document
ADDED
data/.gitignore
ADDED
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
|
data/lib/gizmo/extras.rb
ADDED
@@ -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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|