tap-mechanize 0.5.1 → 0.6.0

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