rsel 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/.gitignore +4 -0
- data/.yardopts +7 -0
- data/Gemfile +2 -0
- data/MIT-LICENSE +22 -0
- data/README.md +35 -0
- data/Rakefile +75 -0
- data/docs/custom.md +87 -0
- data/docs/development.md +48 -0
- data/docs/index.md +13 -0
- data/docs/install.md +33 -0
- data/docs/todo.md +15 -0
- data/docs/usage.md +50 -0
- data/lib/rsel.rb +4 -0
- data/lib/rsel/exceptions.rb +4 -0
- data/lib/rsel/selenium_test.rb +524 -0
- data/rsel.gemspec +29 -0
- data/spec/selenium_test_spec.rb +296 -0
- data/spec/spec_helper.rb +41 -0
- data/test/app.rb +34 -0
- data/test/config.ru +4 -0
- data/test/views/about.erb +9 -0
- data/test/views/form.erb +102 -0
- data/test/views/index.erb +15 -0
- data/vendor/rubyslim-0.1.1/.gitignore +7 -0
- data/vendor/rubyslim-0.1.1/README.md +159 -0
- data/vendor/rubyslim-0.1.1/Rakefile +21 -0
- data/vendor/rubyslim-0.1.1/bin/rubyslim +10 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_deserializer.rb +69 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_executor.rb +12 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_serializer.rb +45 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/ruby_slim.rb +61 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/slim_error.rb +3 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/slim_helper_library.rb +23 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/socket_service.rb +53 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/statement.rb +79 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/statement_executor.rb +174 -0
- data/vendor/rubyslim-0.1.1/lib/rubyslim/table_to_hash_converter.rb +32 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/library_new.rb +13 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/library_old.rb +12 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/should_not_find_test_slim_in_here/test_slim.rb +7 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/simple_script.rb +9 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/test_chain.rb +5 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim.rb +86 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim_with_arguments.rb +23 -0
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim_with_no_sut.rb +5 -0
- data/vendor/rubyslim-0.1.1/rubyslim.gemspec +22 -0
- data/vendor/rubyslim-0.1.1/spec/instance_creation_spec.rb +40 -0
- data/vendor/rubyslim-0.1.1/spec/it8f_spec.rb +8 -0
- data/vendor/rubyslim-0.1.1/spec/list_deserializer_spec.rb +66 -0
- data/vendor/rubyslim-0.1.1/spec/list_executor_spec.rb +187 -0
- data/vendor/rubyslim-0.1.1/spec/list_serialzer_spec.rb +38 -0
- data/vendor/rubyslim-0.1.1/spec/method_invocation_spec.rb +127 -0
- data/vendor/rubyslim-0.1.1/spec/slim_helper_library_spec.rb +80 -0
- data/vendor/rubyslim-0.1.1/spec/socket_service_spec.rb +98 -0
- data/vendor/rubyslim-0.1.1/spec/spec_helper.rb +6 -0
- data/vendor/rubyslim-0.1.1/spec/statement_executor_spec.rb +50 -0
- data/vendor/rubyslim-0.1.1/spec/statement_spec.rb +17 -0
- data/vendor/rubyslim-0.1.1/spec/table_to_hash_converter_spec.rb +31 -0
- metadata +241 -0
data/rsel.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "rsel"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.summary = "Runs Selenium tests from FitNesse"
|
5
|
+
s.description = <<-EOS
|
6
|
+
Rsel provides a Slim fixture for running Selenium tests, with
|
7
|
+
step methods written in Ruby.
|
8
|
+
EOS
|
9
|
+
s.authors = ["Marcus French", "Dale Straw", "Eric Pierce"]
|
10
|
+
s.email = "epierce@automation-excellence.com"
|
11
|
+
s.homepage = "http://github.com/a-e/rsel"
|
12
|
+
s.platform = Gem::Platform::RUBY
|
13
|
+
|
14
|
+
s.add_dependency 'rubyslim-unofficial'
|
15
|
+
s.add_dependency 'xpath'
|
16
|
+
s.add_dependency 'selenium-client'
|
17
|
+
|
18
|
+
s.add_development_dependency 'rake', '0.8.7'
|
19
|
+
s.add_development_dependency 'sinatra'
|
20
|
+
s.add_development_dependency 'mongrel'
|
21
|
+
s.add_development_dependency 'yard'
|
22
|
+
s.add_development_dependency 'rspec', '>= 2.2.0'
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
# Don't include .jar files in distribution
|
26
|
+
s.files.reject! { |f| f =~ /.jar$/ }
|
27
|
+
|
28
|
+
s.require_path = 'lib'
|
29
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Rsel::SeleniumTest do
|
4
|
+
context 'initialization' do
|
5
|
+
before(:each) do
|
6
|
+
@st.visit('/')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "sets correct default configuration" do
|
10
|
+
@st.url.should == 'http://localhost:8070/'
|
11
|
+
@st.browser.host.should == 'localhost'
|
12
|
+
@st.browser.port.should == 4444
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
context 'checkbox' do
|
18
|
+
before(:each) do
|
19
|
+
@st.visit('/form').should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
context "enable" do
|
23
|
+
context "passes when" do
|
24
|
+
it "checkbox with the given label is present" do
|
25
|
+
@st.enable_checkbox("I like cheese").should be_true
|
26
|
+
@st.enable_checkbox("I like salami").should be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "fails when" do
|
31
|
+
it "checkbox with the given label is absent" do
|
32
|
+
@st.enable_checkbox("I dislike bacon").should be_false
|
33
|
+
@st.enable_checkbox("I like broccoli").should be_false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "disable" do
|
39
|
+
context "passes when" do
|
40
|
+
it "checkbox with the given label is present" do
|
41
|
+
@st.disable_checkbox("I like cheese").should be_true
|
42
|
+
@st.disable_checkbox("I like salami").should be_true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
context "fails when" do
|
46
|
+
it "checkbox with the given label is absent" do
|
47
|
+
@st.disable_checkbox("I dislike bacon").should be_false
|
48
|
+
@st.disable_checkbox("I like broccoli").should be_false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "is enabled" do
|
54
|
+
context "passes when" do
|
55
|
+
it "checkbox with the given label exists and is checked" do
|
56
|
+
@st.enable_checkbox("I like cheese").should be_true
|
57
|
+
@st.checkbox_is_enabled("I like cheese").should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "fails when" do
|
62
|
+
it "checkbox with the given label exists but is unchecked" do
|
63
|
+
@st.disable_checkbox("I like cheese").should be_true
|
64
|
+
@st.checkbox_is_enabled("I like cheese").should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "checkbox with the given label does not exist" do
|
68
|
+
@st.checkbox_is_enabled("I dislike bacon").should be_false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "is disabled" do
|
74
|
+
context "passes when" do
|
75
|
+
it "checkbox with the given label exists and is unchecked" do
|
76
|
+
@st.disable_checkbox("I like cheese").should be_true
|
77
|
+
@st.checkbox_is_disabled("I like cheese").should be_true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "fails when" do
|
82
|
+
it "checkbox with the given label exists but is checked" do
|
83
|
+
@st.enable_checkbox("I like cheese").should be_true
|
84
|
+
@st.checkbox_is_disabled("I like cheese").should be_false
|
85
|
+
end
|
86
|
+
|
87
|
+
it "checkbox with the given label does not exist" do
|
88
|
+
@st.checkbox_is_disabled("I dislike bacon").should be_false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
context 'dropdown' do
|
96
|
+
before(:each) do
|
97
|
+
@st.visit('/form').should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
context "select" do
|
101
|
+
context "passes when" do
|
102
|
+
it "value exists in a dropdown" do
|
103
|
+
@st.select_from_dropdown("Tall", "Height").should be_true
|
104
|
+
@st.select_from_dropdown("Medium", "Weight").should be_true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "fails when" do
|
109
|
+
it "dropdown exists, but the value doesn't" do
|
110
|
+
@st.select_from_dropdown("Giant", "Height").should be_false
|
111
|
+
@st.select_from_dropdown("Obese", "Weight").should be_false
|
112
|
+
end
|
113
|
+
|
114
|
+
it "no such dropdown exists" do
|
115
|
+
@st.select_from_dropdown("Over easy", "Eggs").should be_false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "verify" do
|
121
|
+
# TODO
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
context 'navigation' do
|
127
|
+
before(:each) do
|
128
|
+
@st.visit('/').should be_true
|
129
|
+
end
|
130
|
+
|
131
|
+
context "visit" do
|
132
|
+
context "passes when" do
|
133
|
+
it "page exists" do
|
134
|
+
@st.visit("/about").should be_true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "fails when" do
|
139
|
+
it "page does not exist" do
|
140
|
+
@st.visit("/bad/path").should be_false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "reload the current page" do
|
146
|
+
# TODO
|
147
|
+
end
|
148
|
+
|
149
|
+
context "go back to the previous page" do
|
150
|
+
it "passes and loads the correct URL" do
|
151
|
+
@st.visit("/about")
|
152
|
+
@st.visit("/")
|
153
|
+
@st.click_back.should be_true
|
154
|
+
@st.see_title("About this site").should be_true
|
155
|
+
end
|
156
|
+
|
157
|
+
#it "fails when there is no previous page in the history" do
|
158
|
+
# TODO: No obvious way to test this, since everything is running in the
|
159
|
+
# same session
|
160
|
+
#end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "clicking a link" do
|
164
|
+
it "passes and loads the correct page when a link exists" do
|
165
|
+
@st.click_link("About this site").should be_true
|
166
|
+
@st.see_title("About this site").should be_true
|
167
|
+
@st.see("This site is really cool").should be_true
|
168
|
+
end
|
169
|
+
|
170
|
+
it "fails when a link does not exist" do
|
171
|
+
@st.follow("Bogus link").should be_false
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
context 'text field' do
|
178
|
+
before(:each) do
|
179
|
+
@st.visit('/form').should be_true
|
180
|
+
end
|
181
|
+
|
182
|
+
context "type into or fill in" do
|
183
|
+
context "passes when" do
|
184
|
+
it "text field with the given label exists" do
|
185
|
+
@st.type_into_field("Eric", "First name").should be_true
|
186
|
+
@st.fill_in_with("Last name", "Pierce").should be_true
|
187
|
+
end
|
188
|
+
|
189
|
+
it "text field with the given id exists" do
|
190
|
+
@st.type_into_field("Eric", "first_name").should be_true
|
191
|
+
@st.fill_in_with("last_name", "Pierce").should be_true
|
192
|
+
end
|
193
|
+
|
194
|
+
it "texarea with the given label exists" do
|
195
|
+
@st.type_into_field("Blah blah blah", "Life story").should be_true
|
196
|
+
@st.fill_in_with("Life story", "Jibber jabber").should be_true
|
197
|
+
end
|
198
|
+
|
199
|
+
it "texarea with the given id exists" do
|
200
|
+
@st.type_into_field("Blah blah blah", "biography").should be_true
|
201
|
+
@st.fill_in_with("biography", "Jibber jabber").should be_true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "fails when" do
|
206
|
+
it "no field with the given label or id exists" do
|
207
|
+
@st.type_into_field("Matthew", "Middle name").should be_false
|
208
|
+
@st.fill_in_with("middle_name", "Matthew").should be_false
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "should contain" do
|
214
|
+
context "passes when" do
|
215
|
+
it "textarea contains the text" do
|
216
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
217
|
+
@st.field_contains("Life story", "blah").should be_true
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "fails when" do
|
222
|
+
it "textarea does not contain the text" do
|
223
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
224
|
+
@st.field_contains("Life story", "spam").should be_false
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "should equal" do
|
230
|
+
context "passes when" do
|
231
|
+
it "textarea equals the text" do
|
232
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
233
|
+
@st.field_equals("Life story", "Blah dee blah").should be_true
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "fails when" do
|
238
|
+
it "textarea does not exactly equal the text" do
|
239
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
240
|
+
@st.field_equals("Life story", "Blah dee").should be_false
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
context 'visibility' do
|
248
|
+
before(:each) do
|
249
|
+
@st.visit('/').should be_true
|
250
|
+
end
|
251
|
+
|
252
|
+
context "should see" do
|
253
|
+
context "passes when" do
|
254
|
+
it "text is present" do
|
255
|
+
@st.see('Welcome').should be_true
|
256
|
+
@st.see('This is a Sinatra webapp').should be_true
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
context "fails when" do
|
261
|
+
it "text is absent" do
|
262
|
+
@st.see('Nonexistent').should be_false
|
263
|
+
@st.see('Some bogus text').should be_false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
it "is case-sensitive" do
|
268
|
+
@st.see('Sinatra webapp').should be_true
|
269
|
+
@st.see('sinatra Webapp').should be_false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "should not see" do
|
274
|
+
context "passes when" do
|
275
|
+
it "text is absent" do
|
276
|
+
@st.do_not_see('Nonexistent').should be_true
|
277
|
+
@st.do_not_see('Some bogus text').should be_true
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context "fails when" do
|
282
|
+
it "fails when test is present" do
|
283
|
+
@st.do_not_see('Welcome').should be_false
|
284
|
+
@st.do_not_see('This is a Sinatra webapp').should be_false
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
it "is case-sensitive" do
|
289
|
+
@st.do_not_see('Sinatra webapp').should be_false
|
290
|
+
@st.do_not_see('sinatra Webapp').should be_true
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'rsel'
|
3
|
+
require 'selenium/client'
|
4
|
+
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test', 'app'))
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.include Rsel
|
9
|
+
|
10
|
+
config.before(:all) do
|
11
|
+
@st = Rsel::SeleniumTest.new('http://localhost:8070/')
|
12
|
+
@st.open_browser
|
13
|
+
end
|
14
|
+
|
15
|
+
config.after(:all) do
|
16
|
+
@st.close_browser
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Monkeypatch the Selenium::Client::Protocol module,
|
23
|
+
# to prevent http_post from spewing out a bunch of `puts`es on failure.
|
24
|
+
# (It's really distracting when running spec tests)
|
25
|
+
module Selenium
|
26
|
+
module Client
|
27
|
+
module Protocol
|
28
|
+
def http_post(data)
|
29
|
+
start = Time.now
|
30
|
+
called_from = caller.detect{|line| line !~ /(selenium-client|vendor|usr\/lib\/ruby|\(eval\))/i}
|
31
|
+
http = Net::HTTP.new(@host, @port)
|
32
|
+
http.open_timeout = default_timeout_in_seconds
|
33
|
+
http.read_timeout = default_timeout_in_seconds
|
34
|
+
response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
|
35
|
+
# <-- Here is where all the puts statements were -->
|
36
|
+
[ response.body[0..1], response.body ]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
data/test/app.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'sinatra/base'
|
5
|
+
require 'rack'
|
6
|
+
require 'erb'
|
7
|
+
|
8
|
+
class TestApp < Sinatra::Base
|
9
|
+
set :root, File.dirname(__FILE__)
|
10
|
+
set :static, true
|
11
|
+
|
12
|
+
get '/' do
|
13
|
+
erb :index
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/about' do
|
17
|
+
erb :about
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/form' do
|
21
|
+
erb :form
|
22
|
+
end
|
23
|
+
|
24
|
+
# Allow shutting down the app with a request
|
25
|
+
get '/shutdown' do
|
26
|
+
Process.kill('KILL', Process.pid)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
if __FILE__ == $0
|
32
|
+
Rack::Handler::Mongrel.run TestApp, :Port => 8070
|
33
|
+
end
|
34
|
+
|
data/test/config.ru
ADDED
data/test/views/form.erb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head><title>Rsel Test Forms</title></head>
|
4
|
+
<body>
|
5
|
+
<h1>Forms</h1>
|
6
|
+
<p>This page has some random forms to test.</p>
|
7
|
+
|
8
|
+
<div id="person_form">
|
9
|
+
<form action="/thanks" method="get">
|
10
|
+
<p>
|
11
|
+
<label for="first_name">First name</label>
|
12
|
+
<input id="first_name" type="text" />
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
<label for="last_name">Last name</label>
|
16
|
+
<input id="last_name" type="text" />
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
<label for="biography">Life story</label>
|
20
|
+
<textarea id="biography" cols="80" rows="10">
|
21
|
+
</textarea>
|
22
|
+
</p>
|
23
|
+
<p>
|
24
|
+
<label for="height">Height</label>
|
25
|
+
<select id="height">
|
26
|
+
<option value="short">Short</option>
|
27
|
+
<option value="average" selected="selected">Average</option>
|
28
|
+
<option value="tall" >Tall</option>
|
29
|
+
</select>
|
30
|
+
</p>
|
31
|
+
<p>
|
32
|
+
<label for="weight">Weight</label>
|
33
|
+
<select id="weight">
|
34
|
+
<option value="light">Light</option>
|
35
|
+
<option value="medium">Medium</option>
|
36
|
+
<option value="heavy">Heavy</option>
|
37
|
+
</select>
|
38
|
+
</p>
|
39
|
+
<p><button value="submit_person_form">Submit person form</button></p>
|
40
|
+
</form>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<div id="preferences_form">
|
44
|
+
<form action="/thanks" method="get">
|
45
|
+
<p>
|
46
|
+
<label for="favorite_colors">Favorite Colors</label>
|
47
|
+
<select id="favorite_colors" multiple="multiple">
|
48
|
+
<option value="r">Red</option>
|
49
|
+
<option value="g">Green</option>
|
50
|
+
<option value="b">Blue</option>
|
51
|
+
</select>
|
52
|
+
</p>
|
53
|
+
<p>
|
54
|
+
<label for="like_cheese">I like cheese</label>
|
55
|
+
<input id="like_cheese" type="checkbox" checked="checked"/>
|
56
|
+
</p>
|
57
|
+
<p>
|
58
|
+
<label for="like_salami">I like salami</label>
|
59
|
+
<input id="like_salami" type="checkbox" />
|
60
|
+
</p>
|
61
|
+
<table>
|
62
|
+
<tr>
|
63
|
+
<th>Apple</th>
|
64
|
+
<td>
|
65
|
+
<label for="like_apple">Like</label>
|
66
|
+
<input id="like_apple" type="checkbox" checked="checked"/>
|
67
|
+
</td>
|
68
|
+
</tr>
|
69
|
+
<tr>
|
70
|
+
<th>Banana</th>
|
71
|
+
<td>
|
72
|
+
<label for="like_banana">Like</label>
|
73
|
+
<input id="like_banana" type="checkbox"/>
|
74
|
+
</td>
|
75
|
+
</tr>
|
76
|
+
</table>
|
77
|
+
<p>
|
78
|
+
<label for="message">Message</label>
|
79
|
+
<input id="message" type="text" value="Your message goes here" />
|
80
|
+
</p>
|
81
|
+
<p><input type="submit" value="Save preferences" /></p>
|
82
|
+
</form>
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div id="other_form">
|
86
|
+
<form action="/thanks" method="get">
|
87
|
+
<p>
|
88
|
+
<label for="quotes">Quotes</label>
|
89
|
+
<select id="quotes">
|
90
|
+
<option value="1">Single 'quotes'</option>
|
91
|
+
<option value="2">"Double" quotes</option>
|
92
|
+
<option value="3">'Single' and "Double" quotes</option>
|
93
|
+
</select>
|
94
|
+
</p>
|
95
|
+
<p><input id="readonly" type="text" disabled="disabled" /></p>
|
96
|
+
<p><input type="submit" value="Save is disabled" disabled="disabled" /></p>
|
97
|
+
</form>
|
98
|
+
</div>
|
99
|
+
|
100
|
+
</body>
|
101
|
+
</html>
|
102
|
+
|