splinter 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+

|
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
|
+
|