Skip to content

Commit ec23433

Browse files
committed
Add ActionView::TestCase DSL generator
1 parent 05337a0 commit ec23433

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
begin
5+
require "action_view/test_case"
6+
rescue LoadError
7+
return
8+
end
9+
10+
module Tapioca
11+
module Compilers
12+
module Dsl
13+
# `Tapioca::Compilers::Dsl::ActionViewTestHelpers` decorates RBI files for all
14+
# subclasses of `ActionView::TestCase` with the helpers that are included dynamically.
15+
#
16+
# For example, considering the `UsersHelper` module:
17+
#
18+
# ~~~rb
19+
# module UsersHelper
20+
# def current_user_name
21+
# # ...
22+
# end
23+
# end
24+
# ~~~
25+
#
26+
# and its respective test:
27+
#
28+
# ~~~rb
29+
# class UsersHelperTest < ActionView::TestCase
30+
# test "current_user_name works" do
31+
# assert_equal("John", current_user_name)
32+
# end
33+
# end
34+
# ~~~
35+
#
36+
# this generator will produce an RBI file `users_helper_test.rbi` with the following content:
37+
#
38+
# ~~~rbi
39+
# # users_helper_test.rbi
40+
# # typed: strong
41+
# class UsersHelperTest
42+
# include HelperMethods
43+
#
44+
# module HelperMethods
45+
# include ::UsersHelper
46+
# end
47+
# end
48+
# ~~~
49+
class ActionViewTestHelpers < Base
50+
extend T::Sig
51+
52+
sig do
53+
override
54+
.params(root: RBI::Tree, constant: T.class_of(ActionView::TestCase))
55+
.void
56+
end
57+
def decorate(root, constant)
58+
# The helpers are dynamically included in the class when the test is instantiated. The argument for
59+
# initializing the method is just the test name. All of the helper modules are included in the module inside
60+
# _helpers, so we can filter the ancestors based on their names and find all helpers
61+
fake_test = constant.new("fake")
62+
helpers_included = fake_test._helpers.ancestors.select { |mod| mod.name&.end_with?("Helper") }
63+
helper_methods_name = "HelperMethods"
64+
65+
root.create_path(constant) do |klass|
66+
klass.create_include(helper_methods_name)
67+
68+
klass.create_module(helper_methods_name) do |helper_methods|
69+
helpers_included.each do |helper|
70+
helper_methods.create_include(T.must(qualified_name_of(helper)))
71+
end
72+
end
73+
end
74+
end
75+
76+
sig { override.returns(T::Enumerable[Module]) }
77+
def gather_constants
78+
descendants_of(ActionView::TestCase)
79+
end
80+
end
81+
end
82+
end
83+
end
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
## ActionViewTestHelpers
2+
3+
`Tapioca::Compilers::Dsl::ActionViewTestHelpers` decorates RBI files for all
4+
subclasses of `ActionView::TestCase` with the helpers that are included dynamically.
5+
6+
For example, considering the `UsersHelper` module:
7+
8+
~~~rb
9+
module UsersHelper
10+
def current_user_name
11+
# ...
12+
end
13+
end
14+
~~~
15+
16+
and its respective test:
17+
18+
~~~rb
19+
class UsersHelperTest < ActionView::TestCase
20+
test "current_user_name works" do
21+
assert_equal("John", current_user_name)
22+
end
23+
end
24+
~~~
25+
26+
this generator will produce an RBI file `users_helper_test.rbi` with the following content:
27+
28+
~~~rbi
29+
# users_helper_test.rbi
30+
# typed: strong
31+
class UsersHelperTest
32+
include HelperMethods
33+
34+
module HelperMethods
35+
include ::UsersHelper
36+
end
37+
end
38+
~~~

manual/generators.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ In the following section you will find all available DSL generators:
66
* [AASM](generator_aasm.md)
77
* [ActionControllerHelpers](generator_actioncontrollerhelpers.md)
88
* [ActionMailer](generator_actionmailer.md)
9+
* [ActionViewTestHelpers](generator_actionviewtesthelpers.md)
910
* [ActiveJob](generator_activejob.md)
1011
* [ActiveModelAttributes](generator_activemodelattributes.md)
1112
* [ActiveModelSecurePassword](generator_activemodelsecurepassword.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
require "spec_helper"
5+
6+
class Tapioca::Compilers::Dsl::ActionViewTestHelpersSpec < DslSpec
7+
describe("#initialize") do
8+
after(:each) do
9+
T.unsafe(self).assert_no_generated_errors
10+
end
11+
12+
it("doesn't gather anything if there are no ActionView::TestCase tests") do
13+
assert_empty(gathered_constants)
14+
end
15+
16+
it("gathers ActionView::TestCase tests") do
17+
add_ruby_file("users_helper_test.rb", <<~RUBY)
18+
class UsersHelperTest < ActionView::TestCase
19+
end
20+
RUBY
21+
22+
assert_equal(["UsersHelperTest"], gathered_constants)
23+
end
24+
end
25+
26+
describe("#decorate") do
27+
after(:each) do
28+
T.unsafe(self).assert_no_generated_errors
29+
end
30+
31+
it("generates a module with all dynamic helper inclusions") do
32+
add_ruby_file("users_helper.rb", <<~RUBY)
33+
module UsersHelper
34+
def current_user_name
35+
"John"
36+
end
37+
end
38+
RUBY
39+
40+
add_ruby_file("users_helper_test.rb", <<~RUBY)
41+
class UsersHelperTest < ActionView::TestCase
42+
end
43+
RUBY
44+
45+
expected = <<~RBI
46+
# typed: strong
47+
48+
class UsersHelperTest
49+
include HelperMethods
50+
51+
module HelperMethods
52+
include ::UsersHelper
53+
end
54+
end
55+
RBI
56+
57+
assert_equal(expected, rbi_for(:UsersHelperTest))
58+
end
59+
end
60+
end

0 commit comments

Comments
 (0)