forked from cucumber/cucumber-rails
/
javascript_emulation.rb
113 lines (96 loc) · 3.3 KB
/
javascript_emulation.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
module Cucumber
module Rails
module Capybara
module JavascriptEmulation
def self.included(base)
base.class_eval do
alias_method :click_without_javascript_emulation, :click
alias_method :click, :click_with_javascript_emulation
end
end
def click_with_javascript_emulation(*)
if link_with_non_get_http_method?
::Capybara::RackTest::Form.new(driver, js_form(element_node.document, self[:href], emulated_method)).submit(self)
else
click_without_javascript_emulation
end
end
private
def csrf?
csrf_param_node && csrf_token_node
end
def csrf_param_node
element_node.document.at_xpath("//meta[@name='csrf-param']")
end
def csrf_param
csrf_param_node['content']
end
def csrf_token_node
element_node.document.at_xpath("//meta[@name='csrf-token']")
end
def csrf_token
csrf_token_node['content']
end
def js_form(document, action, emulated_method, method = 'POST')
js_form = document.create_element('form')
js_form['action'] = action
js_form['method'] = method
if emulated_method and emulated_method.downcase != method.downcase
input = document.create_element('input')
input['type'] = 'hidden'
input['name'] = '_method'
input['value'] = emulated_method
js_form.add_child(input)
end
# rails will wipe the session if the CSRF token is not sent
# with non-GET requests
if csrf? && emulated_method.downcase != 'get'
input = document.create_element('input')
input['type'] = 'hidden'
input['name'] = csrf_param
input['value'] = csrf_token
js_form.add_child(input)
end
js_form
end
def link_with_non_get_http_method?
if ::Rails.version.to_f >= 3.0
tag_name == 'a' && element_node['data-method'] && element_node['data-method'] =~ /(?:delete|put|post)/
else
tag_name == 'a' && element_node['onclick'] && element_node['onclick'] =~ /var f = document\.createElement\('form'\); f\.style\.display = 'none';/
end
end
def emulated_method
if ::Rails.version.to_f >= 3.0
element_node['data-method']
else
element_node['onclick'][/m\.setAttribute\('value', '([^']*)'\)/, 1]
end
end
def element_node
if self.respond_to? :native
self.native
else
warn 'DEPRECATED: cucumber-rails loves you, just not your version of Capybara. Please update Capybara to >= 0.4.0'
self.node
end
end
end
end
end
end
class Capybara::RackTest::Node
include ::Cucumber::Rails::Capybara::JavascriptEmulation
end
Before('not @no-js-emulation') do
# Enable javascript emulation
::Capybara::RackTest::Node.class_eval do
alias_method :click, :click_with_javascript_emulation
end
end
Before('@no-js-emulation') do
# Disable javascript emulation
::Capybara::RackTest::Node.class_eval do
alias_method :click, :click_without_javascript_emulation
end
end