tap-mechanize 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.6.0 / 2009-05-25
2
+
3
+ Updated to utilize Tap-0.17.0
4
+
1
5
  == 0.5.1 / 2009-03-30
2
6
 
3
7
  * updated dependency on tap-ubiquity to play well on
data/README CHANGED
@@ -12,7 +12,7 @@ configuration files can be edited and resubmitted using a Request task.
12
12
  Multi-step actions, file uploads, and actions that require the use of HTTPS
13
13
  may all be automated in this way.
14
14
 
15
- * Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/9908-tap-task-application/tickets]
15
+ * Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/20532-tap-mechanize/overview]
16
16
  * Github[http://github.com/bahuvrihi/tap-mechanize/tree/master]
17
17
  * {Google Group}[http://groups.google.com/group/ruby-on-tap]
18
18
 
@@ -1,6 +1,7 @@
1
1
  require 'tap/controller'
2
2
  require 'tap/mechanize/utils'
3
3
  require 'tap/ubiquity/utils'
4
+ require 'uri'
4
5
 
5
6
  module Tap
6
7
  module Mechanize
@@ -11,57 +12,57 @@ module Tap
11
12
  include Tap::Ubiquity::Utils
12
13
 
13
14
  PREFIX = '__redirect_http_'
14
- REDIRECT_PARAMETER = '__redirect_http_original_action'
15
15
 
16
16
  # Brings up the tutorial.
17
17
  def index
18
- render 'index.erb', :locals => {:captures => persistence.index }
18
+ render 'index.erb', :locals => {:captures => data.index(:data) }
19
19
  end
20
20
 
21
- def create(id, keep_content=true)
22
- persistence.create(id) do |io|
23
- io << YAML.dump([parse_request(keep_content)])
21
+ def create(id)
22
+ data.create(:data, id) do |io|
23
+ io << YAML.dump([parse_request])
24
24
  end
25
25
  download(id)
26
26
  end
27
27
 
28
28
  def show(id)
29
29
  response['Content-Type'] = "text/plain"
30
- persistence.read(id)
30
+ data.read(:data, id)
31
31
  end
32
32
 
33
33
  def download(id)
34
- path = persistence.path(id)
34
+ path = data.path(:data, id)
35
35
  filename = id
36
36
  filename += ".yml" if File.extname(id) == ""
37
37
 
38
38
  response['Content-Type'] = "text/plain"
39
39
  response['Content-Disposition'] = "attachment; filename=#{filename};"
40
- persistence.read(id)
40
+ data.read(:data, id)
41
41
  end
42
42
 
43
- def update(id="request", keep_content=true)
44
- path = persistence.path(id)
43
+ def update(id="request")
44
+ path = data.path(:data, id)
45
45
  requests = File.exists?(path) ? YAML.load_file(path) : []
46
- requests << parse_request(keep_content)
46
+ requests << parse_request
47
47
 
48
- persistence.update(id) do |io|
48
+ data.create_or_update(:data, id) do |io|
49
49
  io << YAML.dump(requests)
50
50
  end
51
51
  download(id)
52
52
  end
53
53
 
54
54
  def destroy(id)
55
- persistence.destroy(id)
55
+ data.destroy(:data, id)
56
56
  redirect uri(:index)
57
57
  end
58
58
 
59
59
  # Brings up a tutorial teaching how to capture and resubmit forms.
60
60
  def tutorial
61
- serve js_injection(:redirect_http) do |link|
62
- content = render 'tutorial.erb'
63
- content + link
64
- end
61
+ render 'tutorial.erb'
62
+ end
63
+
64
+ def command
65
+ serve js_injection(:redirect_http)
65
66
  end
66
67
 
67
68
  def test
@@ -75,15 +76,26 @@ module Tap
75
76
 
76
77
  # Returns the redirection script.
77
78
  def redirect_http
79
+
80
+ # note configs are formatted into the javascript; keys MUST be valid
81
+ # names, but values can be anything that converts to json
82
+ configs = [
83
+ [:submit_request, false],
84
+ [:keep_content, false],
85
+ [:keep_headers, false],
86
+ [:name, 'request']
87
+ ]
88
+
78
89
  css = render 'redirect.css'
79
90
  script = render 'redirect.js', :locals => {
80
- :redirect_parameter => REDIRECT_PARAMETER,
81
91
  :redirect_action => uri(:update),
92
+ :configs => configs
82
93
  }
83
94
 
84
95
  content = render 'redirect_http.erb', :locals => {
85
96
  :css => css,
86
- :script => script
97
+ :script => script,
98
+ :configs => configs
87
99
  }
88
100
 
89
101
  if request.get?
@@ -137,34 +149,81 @@ if(current = document.getElementById("#{prefix}")) {
137
149
  PREFIX
138
150
  end
139
151
 
140
- def capture_overloaded_parameters # :nodoc:
141
- # perform the actions of Rack::Request::POST, but capture
142
- # overloaded parameter names
152
+ def data
153
+ server.data
154
+ end
155
+
156
+ def uri(*args)
157
+ "http://#{server.host}:#{server.port}#{super}"
158
+ end
159
+
160
+ # Returns the data recieved in the query string.
161
+ def get_params
162
+ env = request.env
163
+ if env["rack.request.query_string"] == request.query_string
164
+ env["rack.request.query_hash"]
165
+ else
166
+ env["rack.request.query_string"] = request.query_string
167
+ env["rack.request.query_hash"] =
168
+ parse_query(request.query_string)
169
+ end
170
+ end
171
+
172
+ # Returns the data recieved in the request body.
173
+ #
174
+ # This method support both application/x-www-form-urlencoded and
175
+ # multipart/form-data.
176
+ def post_params
143
177
  env = request.env
144
- env["rack.request.form_input"] = env["rack.input"]
145
- unless env["rack.request.form_hash"] = parse_multipart(env)
146
- env["rack.request.form_vars"] = env["rack.input"].read
147
- env["rack.request.form_hash"] = Rack::Utils.parse_query(env["rack.request.form_vars"])
148
- env["rack.input"].rewind if env["rack.input"].respond_to?(:rewind)
178
+ if env["rack.request.form_input"].eql? env["rack.input"]
179
+ env["rack.request.form_hash"]
180
+ elsif request.form_data?
181
+ env["rack.request.form_input"] = env["rack.input"]
182
+ unless env["rack.request.form_hash"] =
183
+ Rack::Utils::Multipart.parse_multipart(env)
184
+ form_vars = env["rack.input"].read
185
+
186
+ # Fix for Safari Ajax postings that always append \0
187
+ form_vars.sub!(/\0\z/, '')
188
+
189
+ env["rack.request.form_vars"] = form_vars
190
+ env["rack.request.form_hash"] = parse_query(form_vars)
191
+
192
+ begin
193
+ env["rack.input"].rewind if env["rack.input"].respond_to?(:rewind)
194
+ rescue Errno::ESPIPE
195
+ # Handles exceptions raised by input streams that cannot be rewound
196
+ # such as when using plain CGI under Apache
197
+ end
198
+ end
199
+ env["rack.request.form_hash"]
200
+ else
201
+ {}
149
202
  end
150
203
  end
151
204
 
205
+ def capture_parameters # :nodoc:
206
+ get_params.update(post_params)
207
+ end
208
+
152
209
  # helper to parse the request into a request hash for
153
210
  # use by a Tap::Mechanize::Submit task
154
- def parse_request(keep_content=true) # :nodoc:
155
- if keep_content.kind_of?(String)
156
- keep_content = keep_content =~ /true/i
211
+ def parse_request
212
+ params = capture_parameters
213
+ capture_params = {}
214
+ params.each_key do |key|
215
+ if key =~ /#{prefix}/
216
+ normalize_params(capture_params, key, params.delete(key))
217
+ end
157
218
  end
158
-
159
- capture_overloaded_parameters
219
+ capture_params = capture_params[prefix]
160
220
 
161
221
  hash = {}
162
- parse_rack_request(request, keep_content).each_pair do |key, value|
222
+ parse_rack_request(request, params, capture_params['keep_content'] == "true").each_pair do |key, value|
163
223
  hash[key.to_s] = value
164
224
  end
165
225
 
166
- action = hash['params'].delete(REDIRECT_PARAMETER)
167
-
226
+ action = capture_params['original_action']
168
227
  hash['uri'] = case action
169
228
  when /^http/
170
229
  # action is an href already
@@ -182,8 +241,10 @@ if(current = document.getElementById("#{prefix}")) {
182
241
  File.join(base, action)
183
242
  end
184
243
 
185
- # remove extranous data
186
- hash.delete('headers')
244
+ # remove extra data
245
+ unless capture_params['keep_headers'] == 'true'
246
+ hash.delete('headers')
247
+ end
187
248
  hash.delete('version')
188
249
 
189
250
  hash
@@ -2,7 +2,7 @@ require 'tap/mechanize/request'
2
2
 
3
3
  module Tap
4
4
  module Mechanize
5
- # :startdoc::manifest gets the uri
5
+ # :startdoc::task gets the uri
6
6
  #
7
7
  # Submits an Http request to the specified uri and returns the message
8
8
  # body.
@@ -1,9 +1,10 @@
1
+ require 'tap/task'
1
2
  require 'tap/mechanize/agent'
2
3
 
3
4
  module Tap
4
5
  module Mechanize
5
6
  class Request < Tap::Task
6
- nest :mechanize, Agent # the mechanize agent
7
+ nest :mechanize, Agent, :instance_reader => :mechanize # the mechanize agent
7
8
 
8
9
  # Returns the mechanize agent.
9
10
  #--
@@ -2,7 +2,7 @@ require 'tap/mechanize/request'
2
2
 
3
3
  module Tap
4
4
  module Mechanize
5
- # :startdoc::manifest submits a captured http request
5
+ # :startdoc::task submits a captured http request
6
6
  #
7
7
  # Performs a series of HTTP requests and returns the content of the final
8
8
  # page. Requests must be hashes that at least specify the uri of the next
@@ -10,7 +10,7 @@ module Tap
10
10
  def self.call(env)
11
11
  body = env['rack.input'].read
12
12
  headers = {}
13
- env.each_pair {|key, value| headers[key] = [value] unless key =~ /^rack/ }
13
+ env.each_pair {|key, value| headers[key] = value unless key =~ /^rack/ }
14
14
 
15
15
  [200, headers, [body]]
16
16
  end
@@ -120,7 +120,7 @@ module Tap
120
120
  end
121
121
 
122
122
  # Parses a Rack::Request, with the same activity as parse_http_request.
123
- def parse_rack_request(request, keep_content=true)
123
+ def parse_rack_request(request, request_params, keep_content=true)
124
124
  headers = {}
125
125
  request.env.each_pair do |key, value|
126
126
  key = case key
@@ -134,7 +134,7 @@ module Tap
134
134
  end
135
135
 
136
136
  params = {}
137
- request.params.each_pair do |key, value|
137
+ request_params.each_pair do |key, value|
138
138
  params[key] = each_member(value) do |obj|
139
139
  if obj.kind_of?(Hash)
140
140
  file = {'Content-Type' => obj[:type], 'Filename' => obj[:filename]}
data/tap.yml CHANGED
@@ -1 +0,0 @@
1
- gems: tap-tasks
@@ -1,14 +1,23 @@
1
1
  var RedirectHttp = {
2
- submit_request: false,
3
- keep_content: false,
4
- name: 'request',
2
+ <% configs.each do |(key, value)| %>
3
+ <%= key %>: <%= value.to_json %>,
4
+ <% end %>
5
5
 
6
- /* Returns the target uri for redirection */
7
- redirect_uri: function() {
8
- return '<%= redirect_action %>/' + escape(RedirectHttp.name) + "/" + RedirectHttp.keep_content;
6
+ // Generates a redirection input with the specified value. Inputs
7
+ // have names like '<%= prefix %>[key]' to prevent collisions and
8
+ // facilitate parsing server-side.
9
+ redirect_input: function(key, value) {
10
+ var input = document.createElement("input");
11
+ input.setAttribute("id", '<%= prefix %>[' + key + ']');
12
+ input.setAttribute("name", '<%= prefix %>[' + key + ']');
13
+ input.setAttribute("type", 'hidden');
14
+ input.setAttribute("value", value);
15
+ return input;
9
16
  },
10
17
 
11
- /* Redirects forms and then submits the form if submit is true. */
18
+ // Redirect the form, adds the redirection inputs, and then submits the
19
+ // form, if submit is true or undefined. After submit, the redirection
20
+ // inputs are removed from the form.
12
21
  redirect_form: function(form, submit) {
13
22
  if(typeof submit == 'undefined') { submit = true };
14
23
 
@@ -26,11 +35,23 @@ var RedirectHttp = {
26
35
  }
27
36
  }
28
37
 
29
- // this works without recursing to redirect_form because the onsubmit
30
- // event handler is not executed when a form is submitted by Javascript
31
- form.setAttribute('action', RedirectHttp.redirect_uri());
38
+ // set redirection inputs
39
+ var original_action = form.getAttribute('<%= prefix %>original_action');
40
+ var redirect_inputs = [
41
+ <% configs.each do |(key, value)| %>
42
+ RedirectHttp.redirect_input('<%= key %>', RedirectHttp.<%= key %>),
43
+ <% end %>
44
+ RedirectHttp.redirect_input('original_action', original_action)
45
+ ];
46
+ form.setAttribute('action', '<%= redirect_action %>');
47
+ for(i=0; i<redirect_inputs.length; i++) { form.appendChild(redirect_inputs[i]); }
48
+
32
49
  form.submit();
33
50
 
51
+ // reset redirection inputs
52
+ form.setAttribute('action', original_action);
53
+ for(i=0; i<redirect_inputs.length; i++) { form.removeChild(redirect_inputs[i]); }
54
+
34
55
  if(RedirectHttp.submit_request) {
35
56
  this.revert();
36
57
  form.submit();
@@ -44,13 +65,20 @@ var RedirectHttp = {
44
65
  };
45
66
  },
46
67
 
47
- /* Redirects links and then submits the link if submit is true. */
68
+ // Sumbits the redirected link with redirection parameters in the query
69
+ // string, if submit is true or undefined.
48
70
  redirect_link: function(link, submit) {
49
71
  if(typeof submit == 'undefined') { submit = true };
50
72
 
51
73
  if(submit) {
52
74
  var original_href = link.getAttribute('<%= prefix %>original_href');
53
- location.href = RedirectHttp.redirect_uri() + '?<%= redirect_parameter %>=' + escape(original_href);
75
+ redirect_params = [
76
+ <% configs.each do |(key, value)| %>
77
+ escape('<%= prefix %>[<%= key %>]') + "=" + escape(RedirectHttp.<%= key %>),
78
+ <% end %>
79
+ '<%= prefix %>[original_action]=' + escape(original_href)
80
+ ];
81
+ location.href = '<%= redirect_action %>?' + redirect_params.join("&").replace(/%20/g, "+");
54
82
 
55
83
  if(RedirectHttp.submit_request) {
56
84
  this.revert();
@@ -59,8 +87,9 @@ var RedirectHttp = {
59
87
  };
60
88
  },
61
89
 
62
- /* Wraps the current onX event so that it may be called without interfering
63
- * with the redirection (ie wrapper). */
90
+ // Wraps the current onX event so that it may be called without interfering
91
+ // with the redirection (ie wrapper). Note events are not called again
92
+ // when a form is submitted or a redirection is performed by the wrapper.
64
93
  wrap: function(current, wrapper) {
65
94
  return "try {" +
66
95
  " var <%= prefix %>result = function(<%= prefix %>this) { " +
@@ -72,7 +101,7 @@ var RedirectHttp = {
72
101
  "}; return false;"
73
102
  },
74
103
 
75
- /* Redirects forms and links to '<%= redirect_action %>' */
104
+ // Redirects forms and links to '<%= redirect_action %>'
76
105
  redirect: function() {
77
106
  try {
78
107
 
@@ -85,15 +114,8 @@ var RedirectHttp = {
85
114
  if(form.getAttribute("class") != "<%= prefix %>form") {
86
115
 
87
116
  // store the original action
88
- var input = document.createElement("input");
89
- input.setAttribute("id", '<%= redirect_parameter %>_' + i);
90
- input.setAttribute("name", '<%= redirect_parameter %>');
91
- input.setAttribute("type", 'hidden');
92
- input.setAttribute("value", form.getAttribute('action'));
93
-
94
- form.setAttribute('<%= prefix %>index', i);
95
- form.appendChild(input);
96
-
117
+ form.setAttribute("<%= prefix %>original_action", form.getAttribute('action'));
118
+
97
119
  // redirect onSubmit
98
120
  var current_on_submit = '';
99
121
  if(form.hasAttribute("onSubmit")) current_on_submit = form.getAttribute("onSubmit");
@@ -130,7 +152,7 @@ var RedirectHttp = {
130
152
  }
131
153
  },
132
154
 
133
- /* Reverts redirection and removes the redirection div */
155
+ // Reverts redirection and removes the redirection div
134
156
  revert: function() {
135
157
  try {
136
158
 
@@ -140,13 +162,9 @@ var RedirectHttp = {
140
162
  var form = forms[i];
141
163
 
142
164
  // check in case the form was not redirected
143
- if(form.hasAttribute('<%= prefix %>index')) {
144
- var index = form.getAttribute('<%= prefix %>index');
145
- var input = document.getElementById("<%= redirect_parameter %>_" + index);
146
-
147
- form.setAttribute('action', input.value);
148
- form.removeAttribute('<%= prefix %>index');
149
- form.removeChild(input);
165
+ if(form.hasAttribute('<%= prefix %>original_action')) {
166
+ form.setAttribute('action', form.getAttribute('<%= prefix %>original_action'));
167
+ form.removeAttribute('<%= prefix %>original_action');
150
168
 
151
169
  form.setAttribute('onSubmit', form.getAttribute('<%= prefix %>original_callback'));
152
170
  form.removeAttribute('<%= prefix %>original_callback');
@@ -177,7 +195,7 @@ var RedirectHttp = {
177
195
  if(redirect_http) document.body.removeChild(redirect_http);
178
196
  },
179
197
 
180
- // Alerts of errors due to RedirectHttp
198
+ // Alerts errors due to RedirectHttp
181
199
  alert_error: function(ex) {
182
200
  alert("Redirect HTTP Error: " + ex.message + "\n\n The webpage may have been corrupted; be sure to refresh.");
183
201
  }
@@ -1,8 +1,13 @@
1
1
  <span id='<%= prefix %>message'>Redirecting HTTP Requests</span>
2
2
  <ul id='<%= prefix %>controls' >
3
- <li><input id='<%= prefix %>name' type='text' value='' onchange='javascript:RedirectHttp.name=this.value;'>name</input></li>
4
- <li><input id='<%= prefix %>submit_request' type='checkbox' onchange='javascript:RedirectHttp.submit_request=this.checked;'>submit after capture</input></li>
5
- <li><input id='<%= prefix %>keep_content' type='checkbox' onchange='javascript:RedirectHttp.keep_content=this.checked;'>capture uploaded data</input></li>
3
+ <% configs.each do |(key, value)| %>
4
+ <% case value %>
5
+ <% when true, false %>
6
+ <li><input id='<%= prefix %><%= key %>' type='checkbox' <%= value ? "checked='true' " : '' %>onchange='javascript:RedirectHttp.<%= key %>=this.checked;'><%= key %></input></li>
7
+ <% else %>
8
+ <li><input id='<%= prefix %><%= key %>' type='text' value='<%= value %>' onchange='javascript:RedirectHttp.<%= key %>=this.value;'><%= key %></input></li>
9
+ <% end %>
10
+ <% end %>
6
11
  </ul>
7
12
  <a id='<%= prefix %>revert' href='javascript:RedirectHttp.revert();' class="<%= prefix %>link">close</a>
8
13
 
@@ -55,3 +55,5 @@ demonstrated below:
55
55
  Form with OnSubmit: <input name='words' value="form was submitted"/>
56
56
  <input type="submit" value="submit" />
57
57
  </form>
58
+
59
+ <%= command_link uri(:command) %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tap-mechanize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-30 00:00:00 -06:00
12
+ date: 2009-05-25 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.2.1
23
+ version: 0.3.0
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: tap-tasks
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.0
33
+ version: 0.2.0
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: mechanize