Last active
October 2, 2020 18:03
-
-
Save kuahyeow/36d5b4ac4426f4df35aebc949532ffe9 to your computer and use it in GitHub Desktop.
a rewriter to upgrade to Rails 5.1 style controller test actions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
USAGE: ruby-rewrite -l controller_actions_keyword_args.rb -m <FILE> | |
This rewriter moves your Rails controller tests from `get action, params, session, flash` to | |
`get action, params: params, session: session, flash: flash`. | |
Which is needed if you see the following message in your Rails 5.0 tests : | |
DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated, | |
in favor of keyword arguments, and will be removed in Rails 5.1. | |
Deprecated style: | |
get :show, { id: 1 }, nil, { notice: "This is a flash message" } | |
New keyword style: | |
get :show, params: { id: 1 }, flash: { notice: "This is a flash message" }, | |
session: nil # Can safely be omitted. | |
=end | |
class ControllerActionsKeywordArgs < Parser::Rewriter | |
CONTROLLER_TEST_ACTIONS = %i(get post put patch delete head) | |
def on_send(node) | |
rewrite_controller_test_action(node) | |
write_out_xhr_test_calls(node) | |
super | |
end | |
def rewrite_controller_test_action(node) | |
receiver_node, method_name, *arg_nodes = *node | |
if receiver_node.nil? && CONTROLLER_TEST_ACTIONS.include?(method_name) | |
action, *further_args = arg_nodes | |
unless kwarg_request?(further_args) | |
parameters, session, flash = further_args | |
transform_into_kwarg(parameters, "params") if parameters | |
transform_into_kwarg(session, "session") if session | |
transform_into_kwarg(flash, "flash") if flash | |
end | |
end | |
end | |
def write_out_xhr_test_calls(node) | |
receiver_node, method_name, *arg_nodes = *node | |
if receiver_node.nil? && %i(xhr xml_http_request).include?(method_name) | |
http_method, action, *further_args = arg_nodes | |
http_method_name = http_method.children[0] | |
range = Parser::Source::Range.new(node.loc.expression.source_buffer, node.loc.expression.begin_pos, action.loc.expression.begin_pos) | |
replace(range, http_method_name.to_s + " ") | |
unless kwarg_request?(further_args) | |
parameters, session, flash = further_args | |
transform_into_kwarg(parameters, "params") if parameters | |
transform_into_kwarg(session, "session") if session | |
transform_into_kwarg(flash, "flash") if flash | |
end | |
end | |
#TODO Add `xhr: true` at the end of the statement | |
end | |
protected | |
def transform_into_kwarg(node, keyword) | |
if node.type == :hash && !node.loc.expression.source.match(/\A{.*}\z/m) | |
insert_before node.loc.expression, "#{keyword}: {" | |
insert_after node.loc.expression, "}" | |
else | |
insert_before node.loc.expression, "#{keyword}: " | |
end | |
end | |
REQUEST_KWARGS = %i(params session flash method body xhr) | |
FORMAT_KWARGS = %i(format as) | |
def kwarg_request?(args) | |
return true if args.empty? | |
return false unless args.size == 1 && args[0].type == :hash | |
hash = args[0] | |
hash_pairs = hash.children | |
hash_keys = hash_pairs.map{|n| n.children.first}.flat_map(&:children) | |
hash_keys.all? { |k| FORMAT_KWARGS.include?(k) } || | |
hash_keys.any? { |k| REQUEST_KWARGS.include?(k) } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Needs attention to local variables. Do remember to transform them to something that the view can assess. The traditional way is
@instance_var