splinter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +84 -0
- data/Rakefile +13 -0
- data/lib/splinter.rb +5 -0
- data/lib/splinter/capybara.rb +1 -0
- data/lib/splinter/capybara/actions.rb +138 -0
- data/lib/splinter/capybara/form_completer.rb +45 -0
- data/lib/splinter/perf/deferred_garbage_collection.rb +26 -0
- data/lib/splinter/perf/shared_connection.rb +14 -0
- data/lib/splinter/rspec.rb +12 -0
- data/lib/splinter/rspec/deferred_garbage_collection.rb +11 -0
- data/lib/splinter/rspec/shared_connection.rb +1 -0
- data/lib/splinter/version.rb +3 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/splinter/capybara/actions_spec.rb +98 -0
- data/spec/test_app/server.rb +15 -0
- data/spec/test_app/views/index.erb +272 -0
- metadata +160 -0
data/README.markdown
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Splinter [![Splinter Build Status][Build Icon]][Build Status]
|
2
|
+
|
3
|
+
![](http://i.imgur.com/trnno.jpg)
|
4
|
+
|
5
|
+
Splinter is a Capybara Ninja. It provides some helpers to aid with filling in
|
6
|
+
Rails forms.
|
7
|
+
|
8
|
+
Bonus: Splinter also includes a few performance tweaks which can be used to
|
9
|
+
speed up test suites. These are opt-in.
|
10
|
+
|
11
|
+
[Build Icon]: https://secure.travis-ci.org/site5/splinter.png?branch=master
|
12
|
+
[Build Status]: https://travis-ci.org/site5/splinter
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
gem 'splinter'
|
17
|
+
bundle install
|
18
|
+
|
19
|
+
Add to `spec_helper.rb`:
|
20
|
+
|
21
|
+
require 'splinter/rspec'
|
22
|
+
|
23
|
+
## Performance Tweaks
|
24
|
+
|
25
|
+
Capybara runs in a different thread when the driver is not `rack-test`. This
|
26
|
+
can cause issues with transactional fixtures as ActiveRecord normally creates a
|
27
|
+
new connection per-thread. If you need to force ActiveRecord to share the
|
28
|
+
connection between threads, add the following to `spec_helper`:
|
29
|
+
|
30
|
+
require 'splinter/rspec/shared_connection'
|
31
|
+
|
32
|
+
While not technically related to Capybara, the following GC tweak can increase
|
33
|
+
run time by 10% or more in some suites. To enable it, add the following to
|
34
|
+
`spec_helper`:
|
35
|
+
|
36
|
+
require 'splinter/rspec/deferred_garbage_collection'
|
37
|
+
|
38
|
+
## Screenshots
|
39
|
+
|
40
|
+
To capture screenshots on failure, add the following to `spec_helper`:
|
41
|
+
|
42
|
+
Splinter.screenshot_directory = "/path/to/screenshots"
|
43
|
+
|
44
|
+
## Date/Time/Datetime Helpers
|
45
|
+
|
46
|
+
These are mostly borrowed from [`Hermes::Actions`](http://git.io/bhLQqQ).
|
47
|
+
They're useful for completing the multiple dropdowns required for a
|
48
|
+
date/time/datetime field in a Rails form.
|
49
|
+
|
50
|
+
# Select by CSS ID
|
51
|
+
select_date Time.now, :id_prefix => :publish_at
|
52
|
+
|
53
|
+
# Select by label text, label must have for="id_prefix"
|
54
|
+
select_date Time.now, :from => "Publish at"
|
55
|
+
|
56
|
+
There are also `select_time`, and `select_datetime` variants with the same
|
57
|
+
usage.
|
58
|
+
|
59
|
+
## Completing Forms
|
60
|
+
|
61
|
+
Here's a little sugar to help complete Rails forms:
|
62
|
+
|
63
|
+
complete_form :post do |f|
|
64
|
+
f.text_field :name, "I like turtles!"
|
65
|
+
f.date :publish_at, 3.days.from_now
|
66
|
+
f.select :category, "Blog Posts"
|
67
|
+
f.checkbox :published, false
|
68
|
+
end
|
69
|
+
|
70
|
+
After the block is evaluated, the form is completed and submitted.
|
71
|
+
|
72
|
+
## Note on Patches/Pull Requests
|
73
|
+
|
74
|
+
* Fork the project.
|
75
|
+
* Make your feature addition or bug fix.
|
76
|
+
* Add tests for it. This is important so I don't break it in a future version
|
77
|
+
unintentionally.
|
78
|
+
* Commit, do not bump version. (If you want to have your own version, that is
|
79
|
+
fine but bump version in a commit by itself I can ignore when I pull).
|
80
|
+
* Send me a pull request. Bonus points for topic branches.
|
81
|
+
|
82
|
+
## Copyright
|
83
|
+
|
84
|
+
Copyright (c) 2012 Site5.com. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift 'lib'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new :spec do |t|
|
6
|
+
t.rspec_opts = %w[--color --format documentation]
|
7
|
+
end
|
8
|
+
rescue LoadError
|
9
|
+
puts "Please install rspec (bundle install)"
|
10
|
+
exit
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
data/lib/splinter.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "splinter/capybara/actions"
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'splinter/capybara/form_completer'
|
2
|
+
require 'capybara/dsl'
|
3
|
+
|
4
|
+
module Splinter
|
5
|
+
module Capybara
|
6
|
+
# Additional actions for Capybara.
|
7
|
+
module Actions
|
8
|
+
# Take a screenshot of the current page
|
9
|
+
#
|
10
|
+
# name - The name of the screenshot. Uses the current time by default.
|
11
|
+
def take_screenshot!(name = "#{Time.now.strftime('%Y%m%d%H%M%S%L')}")
|
12
|
+
unless example.metadata[:js]
|
13
|
+
warn "Screenshots can only be captured when an example is tagged with :js => true"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
if path = Splinter.screenshot_directory
|
18
|
+
file = File.join(path, "#{name}.png")
|
19
|
+
page.driver.render(file)
|
20
|
+
puts "Saved screenshot to #{file}"
|
21
|
+
else
|
22
|
+
warn "Splinter.screenshot_directory doesn't exist!"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Complete and submit a form
|
27
|
+
#
|
28
|
+
# base - The name of the form, (eg: :post for form_for @post)
|
29
|
+
#
|
30
|
+
# A required block is yielded to a FormCompleter object. The form will
|
31
|
+
# be completed and submitted upon execution of the block.
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
#
|
35
|
+
# complete_form :post do |f|
|
36
|
+
# f.text_field :author, "Joshua Priddle"
|
37
|
+
# f.text_area :bio, "Lorem ipsum"
|
38
|
+
# f.checkbox :admin, true
|
39
|
+
# f.select :group, 'admins'
|
40
|
+
# f.radio :autosave, false
|
41
|
+
# f.date :publish_at, Time.now
|
42
|
+
# f.datetime :publish_at, Time.now
|
43
|
+
# t.time :publish_at, Time.now
|
44
|
+
# end
|
45
|
+
def complete_form(base)
|
46
|
+
form = FormCompleter.new(base)
|
47
|
+
yield form
|
48
|
+
form.each_input { |method, *args| send(method, *args) }
|
49
|
+
submit_form
|
50
|
+
end
|
51
|
+
|
52
|
+
# Selects hour and minute dropdowns for a time attribute.
|
53
|
+
#
|
54
|
+
# time - A Time object that will be used to choose options.
|
55
|
+
# options - A Hash containing one of:
|
56
|
+
# :id_prefix - the prefix of each dropdown's CSS ID (eg:
|
57
|
+
# :post_publish_at for #post_publish_at_1i, etc)
|
58
|
+
# :from - The text in a label for this dropdown (eg:
|
59
|
+
# "Publish At" for <label for="#publish_at_1i">)
|
60
|
+
def select_datetime(time, options = {})
|
61
|
+
select_prefix = select_prefix_from_options(options)
|
62
|
+
|
63
|
+
select_time time, :id_prefix => select_prefix
|
64
|
+
select_date time, :id_prefix => select_prefix
|
65
|
+
end
|
66
|
+
|
67
|
+
# Selects hour and minute dropdowns for a time attribute.
|
68
|
+
#
|
69
|
+
# time - A Time object that will be used to choose options.
|
70
|
+
# options - A Hash containing one of:
|
71
|
+
# :id_prefix - the prefix of each dropdown's CSS ID (eg:
|
72
|
+
# :post_publish_at for #post_publish_at_1i, etc)
|
73
|
+
# :from - The text in a label for this dropdown (eg:
|
74
|
+
# "Publish At" for <label for="#publish_at_1i">)
|
75
|
+
def select_time(time, options = {})
|
76
|
+
id = select_prefix_from_options(options)
|
77
|
+
|
78
|
+
find_and_select_option "#{id}_4i", "%02d" % time.hour
|
79
|
+
find_and_select_option "#{id}_5i", "%02d" % time.min
|
80
|
+
end
|
81
|
+
|
82
|
+
# Selects hour and minute dropdowns for a time attribute.
|
83
|
+
#
|
84
|
+
# time - A Time object that will be used to choose options.
|
85
|
+
# options - A Hash containing one of:
|
86
|
+
# :id_prefix - the prefix of each dropdown's CSS ID (eg:
|
87
|
+
# :post_publish_at for #post_publish_at_1i, etc)
|
88
|
+
# :from - The text in a label for this dropdown (eg:
|
89
|
+
# "Publish At" for <label for="#publish_at_1i">)
|
90
|
+
def select_date(time, options={})
|
91
|
+
id = select_prefix_from_options(options)
|
92
|
+
|
93
|
+
find_and_select_option "#{id}_1i", time.year
|
94
|
+
find_and_select_option "#{id}_2i", time.month
|
95
|
+
find_and_select_option "#{id}_3i", time.day
|
96
|
+
end
|
97
|
+
|
98
|
+
# Finds and selects an option from a dropdown with the given ID.
|
99
|
+
#
|
100
|
+
# select_id - CSS ID to check, do *not* include #
|
101
|
+
# value - The value to select.
|
102
|
+
def find_and_select_option(select_id, value)
|
103
|
+
select_err = "cannot select option, no select box with id '##{select_id}' found"
|
104
|
+
option_err = "cannot select option, no option with text '#{value}' in select box '##{select_id}'"
|
105
|
+
|
106
|
+
select = find(:css, "##{select_id}", :message => select_err)
|
107
|
+
path = ".//option[contains(./@value, '#{value}')]"
|
108
|
+
|
109
|
+
select.find(:xpath, path, :message => option_err).select_option
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def select_prefix_from_options(options)
|
115
|
+
unless options[:id_prefix] || options[:from]
|
116
|
+
raise ArgumentError, "You must supply either :from or :id_prefix option"
|
117
|
+
end
|
118
|
+
|
119
|
+
select_prefix = options[:id_prefix]
|
120
|
+
select_prefix ||= find_prefix_by_label(options[:from])
|
121
|
+
|
122
|
+
select_prefix
|
123
|
+
end
|
124
|
+
|
125
|
+
def find_prefix_by_label(label)
|
126
|
+
message = "cannot select option, select with label '#{label}' not found"
|
127
|
+
path = "//label[contains(normalize-space(string(.)), '#{label}')]/@for"
|
128
|
+
|
129
|
+
find(:xpath, path, :message => message).text.sub(/_\di$/, '')
|
130
|
+
end
|
131
|
+
|
132
|
+
def submit_form
|
133
|
+
find("form input[type='submit']").click
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Splinter
|
2
|
+
module Capybara
|
3
|
+
# The FormCompleter is a simple stack that keeps track of Capybara actions
|
4
|
+
# to run.
|
5
|
+
class FormCompleter
|
6
|
+
def initialize(base)
|
7
|
+
@base = base
|
8
|
+
@stack = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def text_field(id, value)
|
12
|
+
@stack << [:fill_in, "#{@base}_#{id}", { :with => value.to_s }]
|
13
|
+
end
|
14
|
+
alias text_area text_field
|
15
|
+
|
16
|
+
def checkbox(id, value = nil)
|
17
|
+
@stack << [value ? :check : :uncheck, "#{@base}_#{id}"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def radio(id, value)
|
21
|
+
@stack << [:choose, "#{@base}_#{id}_#{value}"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def select(id, value)
|
25
|
+
@stack << [:find_and_select_option, "#{@base}_#{id}", value]
|
26
|
+
end
|
27
|
+
|
28
|
+
def time(id, value)
|
29
|
+
@stack << [:select_time, value, { :id_prefix => "#{@base}_#{id}" }]
|
30
|
+
end
|
31
|
+
|
32
|
+
def date(id, value)
|
33
|
+
@stack << [:select_date, value, { :id_prefix => "#{@base}_#{id}" }]
|
34
|
+
end
|
35
|
+
|
36
|
+
def datetime(id, value)
|
37
|
+
@stack << [:select_datetime, value, { :id_prefix => "#{@base}_#{id}" }]
|
38
|
+
end
|
39
|
+
|
40
|
+
def each_input(&block)
|
41
|
+
@stack.each(&block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Splinter
|
2
|
+
# Speed up specs by tweaking garbage collection
|
3
|
+
#
|
4
|
+
# See:
|
5
|
+
# http://37signals.com/svn/posts/2742-the-road-to-faster-tests and
|
6
|
+
# https://makandracards.com/makandra/950-speed-up-rspec-by-deferring-garbage-collection
|
7
|
+
class DeferredGarbageCollection
|
8
|
+
|
9
|
+
DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 10.0).to_f
|
10
|
+
|
11
|
+
@@last_gc_run = Time.now
|
12
|
+
|
13
|
+
def self.start
|
14
|
+
GC.disable if DEFERRED_GC_THRESHOLD > 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reconsider
|
18
|
+
if DEFERRED_GC_THRESHOLD > 0 && Time.now - @@last_gc_run >= DEFERRED_GC_THRESHOLD
|
19
|
+
GC.enable
|
20
|
+
GC.start
|
21
|
+
GC.disable
|
22
|
+
@@last_gc_run = Time.now
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This is a hack that forces AR to share its connection between different
|
2
|
+
# threads. Useful for Capybara when you are not using rack-test.
|
3
|
+
class ActiveRecord::Base
|
4
|
+
mattr_accessor :shared_connection
|
5
|
+
@@shared_connection = nil
|
6
|
+
|
7
|
+
def self.connection
|
8
|
+
@@shared_connection || retrieve_connection
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Forces all threads to share the same connection. This works on
|
13
|
+
# Capybara because it starts the web server in a thread.
|
14
|
+
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "splinter/capybara"
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.include Splinter::Capybara::Actions, :type => :request
|
5
|
+
|
6
|
+
config.after :each, :type => :request do
|
7
|
+
take_screenshot! if Splinter.screenshot_directory &&
|
8
|
+
example.exception && example.metadata[:js]
|
9
|
+
|
10
|
+
::Capybara.reset_sessions!
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'splinter/perf/shared_connection'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test_app/server'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe Splinter, :type => :request do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
def time
|
9
|
+
@time ||= Time.now
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_result(name)
|
13
|
+
find("[data-result-for='#{name}']").text
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_selected_option(select_id)
|
17
|
+
find("select##{select_id} > option[selected]").value
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
::Capybara.app = Splinter::TestServer
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#complete_form" do
|
25
|
+
before do
|
26
|
+
visit "/"
|
27
|
+
|
28
|
+
complete_form :post do |f|
|
29
|
+
f.text_field :name, "Josh"
|
30
|
+
f.text_area :content, "Lorem ipsum"
|
31
|
+
f.radio :privacy, "private"
|
32
|
+
f.date :publish_at, time
|
33
|
+
f.datetime :lock_at, time
|
34
|
+
f.checkbox :publish, true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "submitted values" do
|
39
|
+
it { find_result(:name).should == "Josh" }
|
40
|
+
it { find_result(:content).should == "Lorem ipsum" }
|
41
|
+
it { find_result(:privacy).should == "private" }
|
42
|
+
it { find_result("publish_at(1i)").should == time.year.to_s }
|
43
|
+
it { find_result("publish_at(2i)").should == time.month.to_s }
|
44
|
+
it { find_result("publish_at(3i)").should == time.day.to_s }
|
45
|
+
|
46
|
+
it { find_result("lock_at(1i)").should == time.year.to_s }
|
47
|
+
it { find_result("lock_at(2i)").should == time.month.to_s }
|
48
|
+
it { find_result("lock_at(3i)").should == time.day.to_s }
|
49
|
+
it { find_result("lock_at(4i)").should == "%02d" % time.hour }
|
50
|
+
it { find_result("lock_at(5i)").should == "%02d" % time.min }
|
51
|
+
|
52
|
+
it { find_result(:publish).should == '1' }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "time helpers" do
|
57
|
+
let :prefix do
|
58
|
+
"post_lock_at"
|
59
|
+
end
|
60
|
+
|
61
|
+
before do
|
62
|
+
visit "/"
|
63
|
+
end
|
64
|
+
|
65
|
+
{ :id_prefix => "post_lock_at", :from => "Lock at" }.each do |prefix_key, prefix_val|
|
66
|
+
describe "#select_datetime" do
|
67
|
+
it "selects all dropdowns by #{prefix_key.inspect}" do
|
68
|
+
select_datetime time, prefix_key => prefix_val
|
69
|
+
|
70
|
+
find_selected_option("#{prefix}_1i").should == time.year.to_s
|
71
|
+
find_selected_option("#{prefix}_2i").should == time.month.to_s
|
72
|
+
find_selected_option("#{prefix}_3i").should == time.day.to_s
|
73
|
+
find_selected_option("#{prefix}_4i").should == time.hour.to_s
|
74
|
+
find_selected_option("#{prefix}_5i").should == time.min.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#select_time" do
|
79
|
+
it "selects time dropdowns by #{prefix_key.inspect}" do
|
80
|
+
select_time time, prefix_key => prefix_val
|
81
|
+
|
82
|
+
find_selected_option("#{prefix}_4i").should == time.hour.to_s
|
83
|
+
find_selected_option("#{prefix}_5i").should == time.min.to_s
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#select_date" do
|
88
|
+
it "selects date dropdowns by #{prefix_key.inspect}" do
|
89
|
+
select_date time, prefix_key => prefix_val
|
90
|
+
|
91
|
+
find_selected_option("#{prefix}_1i").should == time.year.to_s
|
92
|
+
find_selected_option("#{prefix}_2i").should == time.month.to_s
|
93
|
+
find_selected_option("#{prefix}_3i").should == time.day.to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,272 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Test App</title>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
|
8
|
+
<% if request.post? %>
|
9
|
+
<ul id="results">
|
10
|
+
<% %W(name content privacy publish_at(1i) publish_at(2i) publish_at(3i)
|
11
|
+
publish lock_at(1i) lock_at(2i) lock_at(3i) lock_at(4i) lock_at(5i)).each do |key| %>
|
12
|
+
<li data-result-for="<%= key %>"><%= params[:post][key] %></li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<form action="/" method="post">
|
18
|
+
<p>
|
19
|
+
<label for="post_name">Name</label>
|
20
|
+
<input class="string required" id="post_name" name="post[name]" size="50" type="text" />
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<p>
|
24
|
+
<label for="post_content">Name</label>
|
25
|
+
<textarea id="post_content" name="post[content]"></textarea>
|
26
|
+
</p>
|
27
|
+
|
28
|
+
<p>
|
29
|
+
<label class="radio_buttons required control-label"><abbr title="required">*</abbr> Privacy</label>
|
30
|
+
<label class="radio">
|
31
|
+
<input checked="checked" class="radio_buttons required" id="post_privacy_private" name="post[privacy]" type="radio" value="private" />private
|
32
|
+
</label>
|
33
|
+
<label class="radio">
|
34
|
+
<input class="radio_buttons required" id="post_privacy_public" name="post[privacy]" type="radio" value="public" />public
|
35
|
+
</label>
|
36
|
+
</p>
|
37
|
+
|
38
|
+
<p>
|
39
|
+
<label class="date optional control-label" for="post_publish_at_1i"> Publish at</label>
|
40
|
+
<select class="date optional" id="post_publish_at_1i" name="post[publish_at(1i)]">
|
41
|
+
<option value="2007">2007</option>
|
42
|
+
<option value="2008">2008</option>
|
43
|
+
<option value="2009">2009</option>
|
44
|
+
<option value="2010">2010</option>
|
45
|
+
<option value="2011">2011</option>
|
46
|
+
<option value="2012">2012</option>
|
47
|
+
<option value="2013">2013</option>
|
48
|
+
<option value="2014">2014</option>
|
49
|
+
<option value="2015">2015</option>
|
50
|
+
<option value="2016">2016</option>
|
51
|
+
<option value="2017">2017</option>
|
52
|
+
</select>
|
53
|
+
<select class="date optional" id="post_publish_at_2i" name="post[publish_at(2i)]">
|
54
|
+
<option value="1">January</option>
|
55
|
+
<option value="2">February</option>
|
56
|
+
<option value="3">March</option>
|
57
|
+
<option value="4">April</option>
|
58
|
+
<option value="5">May</option>
|
59
|
+
<option value="6">June</option>
|
60
|
+
<option value="7">July</option>
|
61
|
+
<option value="8">August</option>
|
62
|
+
<option value="9">September</option>
|
63
|
+
<option value="10">October</option>
|
64
|
+
<option value="11">November</option>
|
65
|
+
<option value="12">December</option>
|
66
|
+
</select>
|
67
|
+
<select class="date optional" id="post_publish_at_3i" name="post[publish_at(3i)]">
|
68
|
+
<option value="1">1</option>
|
69
|
+
<option value="2">2</option>
|
70
|
+
<option value="3">3</option>
|
71
|
+
<option value="4">4</option>
|
72
|
+
<option value="5">5</option>
|
73
|
+
<option value="6">6</option>
|
74
|
+
<option value="7">7</option>
|
75
|
+
<option value="8">8</option>
|
76
|
+
<option value="9">9</option>
|
77
|
+
<option value="10">10</option>
|
78
|
+
<option value="11">11</option>
|
79
|
+
<option value="12">12</option>
|
80
|
+
<option value="13">13</option>
|
81
|
+
<option value="14">14</option>
|
82
|
+
<option value="15">15</option>
|
83
|
+
<option value="16">16</option>
|
84
|
+
<option value="17">17</option>
|
85
|
+
<option value="18">18</option>
|
86
|
+
<option value="19">19</option>
|
87
|
+
<option value="20">20</option>
|
88
|
+
<option value="21">21</option>
|
89
|
+
<option value="22">22</option>
|
90
|
+
<option value="23">23</option>
|
91
|
+
<option value="24">24</option>
|
92
|
+
<option value="25">25</option>
|
93
|
+
<option value="26">26</option>
|
94
|
+
<option value="27">27</option>
|
95
|
+
<option value="28">28</option>
|
96
|
+
<option value="29">29</option>
|
97
|
+
<option value="30">30</option>
|
98
|
+
<option value="31">31</option>
|
99
|
+
</select>
|
100
|
+
</p>
|
101
|
+
|
102
|
+
<p>
|
103
|
+
<label class="date optional control-label" for="post_lock_at_1i"> Lock at</label>
|
104
|
+
<select class="date optional" id="post_lock_at_1i" name="post[lock_at(1i)]">
|
105
|
+
<option value="2007">2007</option>
|
106
|
+
<option value="2008">2008</option>
|
107
|
+
<option value="2009">2009</option>
|
108
|
+
<option value="2010">2010</option>
|
109
|
+
<option value="2011">2011</option>
|
110
|
+
<option value="2012">2012</option>
|
111
|
+
<option value="2013">2013</option>
|
112
|
+
<option value="2014">2014</option>
|
113
|
+
<option value="2015">2015</option>
|
114
|
+
<option value="2016">2016</option>
|
115
|
+
<option value="2017">2017</option>
|
116
|
+
</select>
|
117
|
+
<select class="date optional" id="post_lock_at_2i" name="post[lock_at(2i)]">
|
118
|
+
<option value="1">January</option>
|
119
|
+
<option value="2">February</option>
|
120
|
+
<option value="3">March</option>
|
121
|
+
<option value="4">April</option>
|
122
|
+
<option value="5">May</option>
|
123
|
+
<option value="6">June</option>
|
124
|
+
<option value="7">July</option>
|
125
|
+
<option value="8">August</option>
|
126
|
+
<option value="9">September</option>
|
127
|
+
<option value="10">October</option>
|
128
|
+
<option value="11">November</option>
|
129
|
+
<option value="12">December</option>
|
130
|
+
</select>
|
131
|
+
<select class="date optional" id="post_lock_at_3i" name="post[lock_at(3i)]">
|
132
|
+
<option value="1">1</option>
|
133
|
+
<option value="2">2</option>
|
134
|
+
<option value="3">3</option>
|
135
|
+
<option value="4">4</option>
|
136
|
+
<option value="5">5</option>
|
137
|
+
<option value="6">6</option>
|
138
|
+
<option value="7">7</option>
|
139
|
+
<option value="8">8</option>
|
140
|
+
<option value="9">9</option>
|
141
|
+
<option value="10">10</option>
|
142
|
+
<option value="11">11</option>
|
143
|
+
<option value="12">12</option>
|
144
|
+
<option value="13">13</option>
|
145
|
+
<option value="14">14</option>
|
146
|
+
<option value="15">15</option>
|
147
|
+
<option value="16">16</option>
|
148
|
+
<option value="17">17</option>
|
149
|
+
<option value="18">18</option>
|
150
|
+
<option value="19">19</option>
|
151
|
+
<option value="20">20</option>
|
152
|
+
<option value="21">21</option>
|
153
|
+
<option value="22">22</option>
|
154
|
+
<option value="23">23</option>
|
155
|
+
<option value="24">24</option>
|
156
|
+
<option value="25">25</option>
|
157
|
+
<option value="26">26</option>
|
158
|
+
<option value="27">27</option>
|
159
|
+
<option value="28">28</option>
|
160
|
+
<option value="29">29</option>
|
161
|
+
<option value="30">30</option>
|
162
|
+
<option value="31">31</option>
|
163
|
+
</select>
|
164
|
+
—
|
165
|
+
<select class="datetime optional" id="post_lock_at_4i" name="post[lock_at(4i)]">
|
166
|
+
<option value="00">00</option>
|
167
|
+
<option value="01">01</option>
|
168
|
+
<option value="02">02</option>
|
169
|
+
<option value="03">03</option>
|
170
|
+
<option value="04">04</option>
|
171
|
+
<option value="05">05</option>
|
172
|
+
<option value="06">06</option>
|
173
|
+
<option value="07">07</option>
|
174
|
+
<option value="08">08</option>
|
175
|
+
<option value="09">09</option>
|
176
|
+
<option value="10">10</option>
|
177
|
+
<option value="11">11</option>
|
178
|
+
<option value="12">12</option>
|
179
|
+
<option value="13">13</option>
|
180
|
+
<option value="14">14</option>
|
181
|
+
<option value="15">15</option>
|
182
|
+
<option value="16">16</option>
|
183
|
+
<option value="17">17</option>
|
184
|
+
<option value="18">18</option>
|
185
|
+
<option value="19">19</option>
|
186
|
+
<option value="20">20</option>
|
187
|
+
<option value="21">21</option>
|
188
|
+
<option value="22">22</option>
|
189
|
+
<option value="23">23</option>
|
190
|
+
</select> :
|
191
|
+
<select class="datetime optional" id="post_lock_at_5i" name="post[lock_at(5i)]">
|
192
|
+
<option value="00">00</option>
|
193
|
+
<option value="01">01</option>
|
194
|
+
<option value="02">02</option>
|
195
|
+
<option value="03">03</option>
|
196
|
+
<option value="04">04</option>
|
197
|
+
<option value="05">05</option>
|
198
|
+
<option value="06">06</option>
|
199
|
+
<option value="07">07</option>
|
200
|
+
<option value="08">08</option>
|
201
|
+
<option value="09">09</option>
|
202
|
+
<option value="10">10</option>
|
203
|
+
<option value="11">11</option>
|
204
|
+
<option value="12">12</option>
|
205
|
+
<option value="13">13</option>
|
206
|
+
<option value="14">14</option>
|
207
|
+
<option value="15">15</option>
|
208
|
+
<option value="16">16</option>
|
209
|
+
<option value="17">17</option>
|
210
|
+
<option value="18">18</option>
|
211
|
+
<option value="19">19</option>
|
212
|
+
<option value="20">20</option>
|
213
|
+
<option value="21">21</option>
|
214
|
+
<option value="22">22</option>
|
215
|
+
<option value="23">23</option>
|
216
|
+
<option value="24">24</option>
|
217
|
+
<option value="25">25</option>
|
218
|
+
<option value="26">26</option>
|
219
|
+
<option value="27">27</option>
|
220
|
+
<option value="28">28</option>
|
221
|
+
<option value="29">29</option>
|
222
|
+
<option value="30">30</option>
|
223
|
+
<option value="31">31</option>
|
224
|
+
<option value="32">32</option>
|
225
|
+
<option value="33">33</option>
|
226
|
+
<option value="34">34</option>
|
227
|
+
<option value="35">35</option>
|
228
|
+
<option value="36">36</option>
|
229
|
+
<option value="37">37</option>
|
230
|
+
<option value="38">38</option>
|
231
|
+
<option value="39">39</option>
|
232
|
+
<option value="40">40</option>
|
233
|
+
<option value="41">41</option>
|
234
|
+
<option value="42">42</option>
|
235
|
+
<option value="43">43</option>
|
236
|
+
<option value="44">44</option>
|
237
|
+
<option value="45">45</option>
|
238
|
+
<option value="46">46</option>
|
239
|
+
<option value="47">47</option>
|
240
|
+
<option value="48">48</option>
|
241
|
+
<option value="49">49</option>
|
242
|
+
<option value="50">50</option>
|
243
|
+
<option value="51">51</option>
|
244
|
+
<option value="52">52</option>
|
245
|
+
<option value="53">53</option>
|
246
|
+
<option value="54">54</option>
|
247
|
+
<option value="55">55</option>
|
248
|
+
<option value="56">56</option>
|
249
|
+
<option value="57">57</option>
|
250
|
+
<option value="58">58</option>
|
251
|
+
<option value="59">59</option>
|
252
|
+
</select>
|
253
|
+
</p>
|
254
|
+
|
255
|
+
<p>
|
256
|
+
<label class="boolean optional control-label" for="post_publish"> Publish</label>
|
257
|
+
<div class="controls">
|
258
|
+
<input name="post[publish]" type="hidden" value="0" />
|
259
|
+
<label class="checkbox">
|
260
|
+
<input checked="checked" class="boolean optional" id="post_publish" name="post[publish]" type="checkbox" value="1" />
|
261
|
+
</label>
|
262
|
+
</div>
|
263
|
+
</p>
|
264
|
+
|
265
|
+
<p>
|
266
|
+
<input name="commit" type="submit" value="Create" />
|
267
|
+
</p>
|
268
|
+
</form>
|
269
|
+
|
270
|
+
|
271
|
+
</body>
|
272
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: splinter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joshua Priddle
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-03-16 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: capybara
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 47
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 8
|
47
|
+
- 0
|
48
|
+
version: 2.8.0
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: sinatra
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 31
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 3
|
63
|
+
- 2
|
64
|
+
version: 1.3.2
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rake
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 11
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
- 9
|
79
|
+
- 2
|
80
|
+
- 2
|
81
|
+
version: 0.9.2.2
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rack-test
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ~>
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 5
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
- 6
|
96
|
+
- 1
|
97
|
+
version: 0.6.1
|
98
|
+
type: :development
|
99
|
+
version_requirements: *id005
|
100
|
+
description:
|
101
|
+
email: jpriddle@me.com
|
102
|
+
executables: []
|
103
|
+
|
104
|
+
extensions: []
|
105
|
+
|
106
|
+
extra_rdoc_files:
|
107
|
+
- README.markdown
|
108
|
+
files:
|
109
|
+
- Rakefile
|
110
|
+
- README.markdown
|
111
|
+
- lib/splinter/capybara/actions.rb
|
112
|
+
- lib/splinter/capybara/form_completer.rb
|
113
|
+
- lib/splinter/capybara.rb
|
114
|
+
- lib/splinter/perf/deferred_garbage_collection.rb
|
115
|
+
- lib/splinter/perf/shared_connection.rb
|
116
|
+
- lib/splinter/rspec/deferred_garbage_collection.rb
|
117
|
+
- lib/splinter/rspec/shared_connection.rb
|
118
|
+
- lib/splinter/rspec.rb
|
119
|
+
- lib/splinter/version.rb
|
120
|
+
- lib/splinter.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
- spec/splinter/capybara/actions_spec.rb
|
123
|
+
- spec/test_app/server.rb
|
124
|
+
- spec/test_app/views/index.erb
|
125
|
+
has_rdoc: true
|
126
|
+
homepage: https://github.com/site5/splinter
|
127
|
+
licenses: []
|
128
|
+
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options:
|
131
|
+
- --charset=UTF-8
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
hash: 3
|
149
|
+
segments:
|
150
|
+
- 0
|
151
|
+
version: "0"
|
152
|
+
requirements: []
|
153
|
+
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 1.6.2
|
156
|
+
signing_key:
|
157
|
+
specification_version: 3
|
158
|
+
summary: Splinter is a Capybara Ninja
|
159
|
+
test_files: []
|
160
|
+
|