-
Notifications
You must be signed in to change notification settings - Fork 112
/
dsl_spec.rb
113 lines (95 loc) · 2.8 KB
/
dsl_spec.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
# typed: strict
# frozen_string_literal: true
require "sorbet-runtime"
require "minitest/spec"
require "content_helper"
require "template_helper"
require "isolation_helper"
class DslSpec < Minitest::Spec
extend T::Sig
include Kernel
include ContentHelper
include TemplateHelper
include IsolationHelper
sig { void }
def after_setup
# Require the file that the target class should be loaded from
require(T.unsafe(self).target_class_file)
end
subject do
# Get the class under test and initialize a new instance of it
# as the "subject"
class_name = T.unsafe(self).target_class_name
Object.const_get(class_name).new
end
sig { returns(Class) }
def spec_test_class
# Find the spec test class
klass = T.unsafe(self).class
# It should be the one that directly inherits from DslSpec
klass = klass.superclass while klass.superclass != DslSpec
klass
end
sig { returns(String) }
def target_class_name
# Get the name of the class under test from the name of the
# test class
T.must(spec_test_class.name).gsub(/Spec$/, "")
end
sig { returns(String) }
def target_class_file
underscore(target_class_name)
end
sig { params(class_name: String).returns(String) }
def underscore(class_name)
return class_name unless /[A-Z-]|::/.match?(class_name)
word = class_name.to_s.gsub("::", "/")
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
word.tr!("-", "_")
word.downcase!
word
end
sig { params(str: String, indent: Integer).returns(String) }
def indented(str, indent)
str.lines.map! do |line|
next line if line.chomp.empty?
" " * indent + line
end.join
end
sig { returns(T::Array[String]) }
def gathered_constants
T.unsafe(self).subject.processable_constants.map(&:name).sort
end
sig do
params(
constant_name: T.any(Symbol, String)
).returns(String)
end
def rbi_for(constant_name)
# Sometimes gather_constants registers temp constants, so
# let's call it once to ensure all constants are in place.
T.unsafe(self).subject.processable_constants
file = RBI::File.new(strictness: "strong")
constant = Object.const_get(constant_name)
T.unsafe(self).subject.decorate(file.root, constant)
file.root.nest_non_public_methods!
file.root.group_nodes!
file.root.sort_nodes!
file.string.tap do |str|
output = Tapioca::Compilers::Sorbet.run(
"--no-config",
"--stop-after",
"parser",
"-e",
str,
quiet: false
)
assert($?.success?, <<~MSG) # rubocop:disable Style/SpecialGlobalVars
Expected generated RBI file for `#{constant_name}` with no parsing errors.
Got these parsing errors:
#{indented(output, 2)}
MSG
end
end
end