dommy-rails 0.9.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.
- checksums.yaml +7 -0
- data/README.md +129 -0
- data/lib/dommy/rails/aria_snapshot_matching.rb +100 -0
- data/lib/dommy/rails/browser_spec.rb +148 -0
- data/lib/dommy/rails/dom_source.rb +35 -0
- data/lib/dommy/rails/form_inspector.rb +52 -0
- data/lib/dommy/rails/lint.rb +109 -0
- data/lib/dommy/rails/mail_part.rb +32 -0
- data/lib/dommy/rails/match_target.rb +23 -0
- data/lib/dommy/rails/minitest/assertions.rb +298 -0
- data/lib/dommy/rails/minitest/integration.rb +13 -0
- data/lib/dommy/rails/minitest.rb +4 -0
- data/lib/dommy/rails/page_inspector.rb +66 -0
- data/lib/dommy/rails/rspec/browser.rb +40 -0
- data/lib/dommy/rails/rspec/integration.rb +16 -0
- data/lib/dommy/rails/rspec/matchers.rb +793 -0
- data/lib/dommy/rails/rspec.rb +12 -0
- data/lib/dommy/rails/stimulus.rb +50 -0
- data/lib/dommy/rails/turbo_stream.rb +40 -0
- data/lib/dommy/rails/url_matcher.rb +26 -0
- data/lib/dommy/rails/url_normalizer.rb +45 -0
- data/lib/dommy/rails/version.rb +5 -0
- data/lib/dommy/rails.rb +18 -0
- metadata +78 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
module Dommy
|
|
2
|
+
module Rails
|
|
3
|
+
module Minitest
|
|
4
|
+
module Assertions
|
|
5
|
+
def assert_dom_has_css(scope, selector, text: nil, count: nil, msg: nil)
|
|
6
|
+
assert_dom_contains(scope, selector, text: text, count: count, msg: msg)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def refute_dom_has_css(scope, selector, text: nil, count: nil, msg: nil)
|
|
10
|
+
refute_dom_contains(scope, selector, text: text, count: count, msg: msg)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def assert_dom_has_text(scope, text, msg: nil)
|
|
14
|
+
assert_dom_contains_text(scope, text, msg: msg)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def refute_dom_has_text(scope, text, msg: nil)
|
|
18
|
+
refute_dom_contains_text(scope, text, msg: msg)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def assert_dom_has_xpath(actual, expression, text: nil, count: nil, msg: nil)
|
|
22
|
+
matched = Dommy::Rails::PageInspector.xpath_matches(dom_document_for(actual), expression, text: text)
|
|
23
|
+
msg ||= "expected to contain XPath #{expression.inspect}#{text ? " with text #{text.inspect}" : ""}, found #{matched.size}"
|
|
24
|
+
assert(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def refute_dom_has_xpath(actual, expression, text: nil, count: nil, msg: nil)
|
|
28
|
+
matched = Dommy::Rails::PageInspector.xpath_matches(dom_document_for(actual), expression, text: text)
|
|
29
|
+
msg ||= "expected NOT to contain XPath #{expression.inspect}#{text ? " with text #{text.inspect}" : ""}, found #{matched.size}"
|
|
30
|
+
refute(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def assert_dom_has_title(actual, expected, msg: nil)
|
|
34
|
+
matched = Dommy::Rails::PageInspector.title_matches?(dom_document_for(actual), expected)
|
|
35
|
+
msg ||= "expected document title to match #{expected.inspect}"
|
|
36
|
+
assert(matched, msg)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def refute_dom_has_title(actual, expected, msg: nil)
|
|
40
|
+
matched = Dommy::Rails::PageInspector.title_matches?(dom_document_for(actual), expected)
|
|
41
|
+
msg ||= "expected document title NOT to match #{expected.inspect}"
|
|
42
|
+
refute(matched, msg)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Assert the subject's ARIA snapshot matches `expected` (Playwright-style
|
|
46
|
+
# subset; names may be /regex/).
|
|
47
|
+
def assert_aria_snapshot(expected, actual, msg: nil)
|
|
48
|
+
snapshot = dom_document_for(actual).aria_snapshot
|
|
49
|
+
msg ||= "expected aria snapshot to match:\n#{expected}\ngot:\n#{snapshot}"
|
|
50
|
+
assert(Dommy::Rails::AriaSnapshotMatching.matches?(snapshot, expected), msg)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def assert_dom_has_meta(actual, name: nil, property: nil, content: nil, msg: nil)
|
|
54
|
+
matched = Dommy::Rails::PageInspector.meta_matches?(dom_document_for(actual), name: name, property: property, content: content)
|
|
55
|
+
msg ||= "expected to find meta #{meta_desc(name: name, property: property, content: content)}"
|
|
56
|
+
assert(matched, msg)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def refute_dom_has_meta(actual, name: nil, property: nil, content: nil, msg: nil)
|
|
60
|
+
matched = Dommy::Rails::PageInspector.meta_matches?(dom_document_for(actual), name: name, property: property, content: content)
|
|
61
|
+
msg ||= "expected NOT to find meta #{meta_desc(name: name, property: property, content: content)}"
|
|
62
|
+
refute(matched, msg)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def assert_dom_has_csrf_meta_tags(actual, msg: nil)
|
|
66
|
+
matched = Dommy::Rails::PageInspector.csrf_meta_tags?(dom_document_for(actual))
|
|
67
|
+
msg ||= "expected to find Rails CSRF meta tags"
|
|
68
|
+
assert(matched, msg)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def assert_dom_has_authenticity_token(actual, msg: nil)
|
|
72
|
+
matched = Dommy::Rails::PageInspector.authenticity_token?(dom_document_for(actual))
|
|
73
|
+
msg ||= "expected to find Rails authenticity token field"
|
|
74
|
+
assert(matched, msg)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def assert_dom_has_link(actual, text = nil, href: nil, count: nil, msg: nil)
|
|
78
|
+
matched = Dommy::Rails::PageInspector.links(dom_document_for(actual), text: text, href: href)
|
|
79
|
+
msg ||= "expected to contain link#{text ? " with text #{text.inspect}" : ""}#{href ? " with href #{href.inspect}" : ""}, found #{matched.size}"
|
|
80
|
+
assert(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def refute_dom_has_link(actual, text = nil, href: nil, count: nil, msg: nil)
|
|
84
|
+
matched = Dommy::Rails::PageInspector.links(dom_document_for(actual), text: text, href: href)
|
|
85
|
+
msg ||= "expected NOT to contain link#{text ? " with text #{text.inspect}" : ""}#{href ? " with href #{href.inspect}" : ""}, found #{matched.size}"
|
|
86
|
+
refute(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def assert_dom_has_turbo_frame(actual, id = nil, text: nil, count: nil, msg: nil)
|
|
90
|
+
matched = Dommy::Rails::PageInspector.turbo_frames(dom_document_for(actual), id, text: text)
|
|
91
|
+
msg ||= "expected to contain turbo-frame#{id ? " ##{id}" : ""}#{text ? " with text #{text.inspect}" : ""}, found #{matched.size}"
|
|
92
|
+
assert(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
93
|
+
yield matched.first if block_given? && matched.any?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def refute_dom_has_turbo_frame(actual, id = nil, text: nil, count: nil, msg: nil)
|
|
97
|
+
matched = Dommy::Rails::PageInspector.turbo_frames(dom_document_for(actual), id, text: text)
|
|
98
|
+
msg ||= "expected NOT to contain turbo-frame#{id ? " ##{id}" : ""}#{text ? " with text #{text.inspect}" : ""}, found #{matched.size}"
|
|
99
|
+
refute(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def assert_dom_has_select(actual, name = nil, label: nil, count: nil, msg: nil)
|
|
103
|
+
matched = Dommy::Rails::PageInspector.selects(dom_document_for(actual), name: name, label: label)
|
|
104
|
+
msg ||= "expected to contain select#{name ? " with name #{name.inspect}" : ""}#{label ? " with label #{label.inspect}" : ""}, found #{matched.size}"
|
|
105
|
+
assert(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def refute_dom_has_select(actual, name = nil, label: nil, count: nil, msg: nil)
|
|
109
|
+
matched = Dommy::Rails::PageInspector.selects(dom_document_for(actual), name: name, label: label)
|
|
110
|
+
msg ||= "expected NOT to contain select#{name ? " with name #{name.inspect}" : ""}#{label ? " with label #{label.inspect}" : ""}, found #{matched.size}"
|
|
111
|
+
refute(Dommy::Internal::DomMatching.count_matches?(matched.size, count), msg)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def assert_dom_has_checked_field(actual, name = nil, msg: nil)
|
|
115
|
+
matched = Dommy::Rails::PageInspector.checkable_fields(dom_document_for(actual), name: name, checked: true)
|
|
116
|
+
msg ||= "expected to find checked field#{name ? " #{name.inspect}" : ""}"
|
|
117
|
+
assert(matched.any?, msg)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def assert_dom_has_unchecked_field(actual, name = nil, msg: nil)
|
|
121
|
+
matched = Dommy::Rails::PageInspector.checkable_fields(dom_document_for(actual), name: name, checked: false)
|
|
122
|
+
msg ||= "expected to find unchecked field#{name ? " #{name.inspect}" : ""}"
|
|
123
|
+
assert(matched.any?, msg)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def assert_dom_has_form(actual, action: nil, method: nil, model: nil, msg: nil)
|
|
127
|
+
document = dom_document_for(actual)
|
|
128
|
+
matched = Dommy::Rails::FormInspector.matches?(document, action: action, method: method, model: model)
|
|
129
|
+
msg ||= "expected to find form matching #{form_desc(action: action, method: method, model: model)}"
|
|
130
|
+
assert(matched, msg)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def refute_dom_has_form(actual, action: nil, method: nil, model: nil, msg: nil)
|
|
134
|
+
document = dom_document_for(actual)
|
|
135
|
+
matched = Dommy::Rails::FormInspector.matches?(document, action: action, method: method, model: model)
|
|
136
|
+
msg ||= "expected NOT to find form matching #{form_desc(action: action, method: method, model: model)}"
|
|
137
|
+
refute(matched, msg)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def assert_dom_has_turbo_stream(actual, action:, target:, msg: nil)
|
|
141
|
+
stream = Dommy::Rails::TurboStream.find(dom_body_for(actual), action: action, target: target)
|
|
142
|
+
msg ||= "expected to find turbo-stream action=#{action} target=#{target}"
|
|
143
|
+
assert(stream, msg)
|
|
144
|
+
yield Dommy::Rails::TurboStream.fragment_document(stream) if block_given? && stream
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def refute_dom_has_turbo_stream(actual, action:, target:, msg: nil)
|
|
148
|
+
matched = Dommy::Rails::TurboStream.matches?(dom_body_for(actual), action: action, target: target)
|
|
149
|
+
msg ||= "expected NOT to find turbo-stream action=#{action} target=#{target}"
|
|
150
|
+
refute(matched, msg)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def assert_dom_appends_turbo_stream(actual, target, msg: nil, &block)
|
|
154
|
+
assert_dom_has_turbo_stream(actual, action: "append", target: target, msg: msg, &block)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def assert_dom_replaces_turbo_stream(actual, target, msg: nil, &block)
|
|
158
|
+
assert_dom_has_turbo_stream(actual, action: "replace", target: target, msg: msg, &block)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def assert_dom_updates_turbo_stream(actual, target, msg: nil, &block)
|
|
162
|
+
assert_dom_has_turbo_stream(actual, action: "update", target: target, msg: msg, &block)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def assert_dom_removes_turbo_stream(actual, target, msg: nil, &block)
|
|
166
|
+
assert_dom_has_turbo_stream(actual, action: "remove", target: target, msg: msg, &block)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def assert_dom_has_stimulus_controller(actual, name, msg: nil)
|
|
170
|
+
matched = Dommy::Rails::Stimulus.controller?(dom_document_for(actual), name)
|
|
171
|
+
msg ||= "expected to find element with Stimulus controller '#{name}'"
|
|
172
|
+
assert(matched, msg)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def refute_dom_has_stimulus_controller(actual, name, msg: nil)
|
|
176
|
+
matched = Dommy::Rails::Stimulus.controller?(dom_document_for(actual), name)
|
|
177
|
+
msg ||= "expected NOT to find element with Stimulus controller '#{name}'"
|
|
178
|
+
refute(matched, msg)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def assert_dom_has_stimulus_action(actual, action, msg: nil)
|
|
182
|
+
matched = Dommy::Rails::Stimulus.action?(dom_document_for(actual), action)
|
|
183
|
+
msg ||= "expected to find element with Stimulus action '#{action}'"
|
|
184
|
+
assert(matched, msg)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def refute_dom_has_stimulus_action(actual, action, msg: nil)
|
|
188
|
+
matched = Dommy::Rails::Stimulus.action?(dom_document_for(actual), action)
|
|
189
|
+
msg ||= "expected NOT to find element with Stimulus action '#{action}'"
|
|
190
|
+
refute(matched, msg)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def assert_dom_has_stimulus_target(actual, controller, target, msg: nil)
|
|
194
|
+
matched = Dommy::Rails::Stimulus.target?(dom_document_for(actual), controller, target)
|
|
195
|
+
msg ||= "expected to find element with Stimulus target '#{controller}.#{target}'"
|
|
196
|
+
assert(matched, msg)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def refute_dom_has_stimulus_target(actual, controller, target, msg: nil)
|
|
200
|
+
matched = Dommy::Rails::Stimulus.target?(dom_document_for(actual), controller, target)
|
|
201
|
+
msg ||= "expected NOT to find element with Stimulus target '#{controller}.#{target}'"
|
|
202
|
+
refute(matched, msg)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def assert_dom_has_stimulus_value(actual, controller, key, value, msg: nil)
|
|
206
|
+
matched = Dommy::Rails::Stimulus.value?(dom_document_for(actual), controller, key, value)
|
|
207
|
+
msg ||= "expected to find element with Stimulus value '#{controller}.#{key}' = #{value.inspect}"
|
|
208
|
+
assert(matched, msg)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def refute_dom_has_stimulus_value(actual, controller, key, value, msg: nil)
|
|
212
|
+
matched = Dommy::Rails::Stimulus.value?(dom_document_for(actual), controller, key, value)
|
|
213
|
+
msg ||= "expected NOT to find element with Stimulus value '#{controller}.#{key}' = #{value.inspect}"
|
|
214
|
+
refute(matched, msg)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def assert_dom_no_duplicate_ids(actual, msg: nil)
|
|
218
|
+
document = dom_document_for(actual)
|
|
219
|
+
duplicates = Dommy::Rails::Lint.duplicate_ids(document)
|
|
220
|
+
msg ||= "expected no duplicate IDs, found: #{duplicates.join(', ')}"
|
|
221
|
+
assert(duplicates.empty?, msg)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def assert_dom_no_invalid_aria_references(actual, msg: nil)
|
|
225
|
+
document = dom_document_for(actual)
|
|
226
|
+
issues = Dommy::Rails::Lint.invalid_aria_references(document)
|
|
227
|
+
msg ||= "expected no invalid ARIA references, found #{issues.size} issues"
|
|
228
|
+
assert(issues.empty?, msg)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def assert_dom_no_missing_form_labels(actual, msg: nil)
|
|
232
|
+
document = dom_document_for(actual)
|
|
233
|
+
issues = Dommy::Rails::Lint.missing_form_labels(document)
|
|
234
|
+
msg ||= "expected no missing form labels, found #{issues.size} issues"
|
|
235
|
+
assert(issues.empty?, msg)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def assert_dom_no_empty_links(actual, msg: nil)
|
|
239
|
+
issues = Dommy::Rails::Lint.empty_links(dom_document_for(actual))
|
|
240
|
+
msg ||= "expected no empty links, found #{issues.size} issues"
|
|
241
|
+
assert(issues.empty?, msg)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def assert_dom_no_nested_interactive_elements(actual, msg: nil)
|
|
245
|
+
issues = Dommy::Rails::Lint.nested_interactive_elements(dom_document_for(actual))
|
|
246
|
+
msg ||= "expected no nested interactive elements, found #{issues.size} issues"
|
|
247
|
+
assert(issues.empty?, msg)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def assert_mail_has_html_link(mail, text = nil, href: nil, count: nil, msg: nil)
|
|
251
|
+
document = Dommy::Rails::MailPart.html_document(mail)
|
|
252
|
+
msg ||= "expected mail to have an HTML part"
|
|
253
|
+
assert(document, msg)
|
|
254
|
+
assert_dom_has_link(document, text, href: href, count: count, msg: msg)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def assert_mail_has_html_text(mail, text, msg: nil)
|
|
258
|
+
document = Dommy::Rails::MailPart.html_document(mail)
|
|
259
|
+
msg ||= "expected mail HTML to contain #{text.inspect}"
|
|
260
|
+
assert(document, "expected mail to have an HTML part")
|
|
261
|
+
assert_dom_has_text(document, text, msg: msg)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def assert_mail_has_plain_text(mail, text, msg: nil)
|
|
265
|
+
body = Dommy::Rails::MailPart.plain_body(mail).to_s
|
|
266
|
+
msg ||= "expected mail plain text to contain #{text.inspect}, got #{body.inspect}"
|
|
267
|
+
assert(Dommy::Internal::DomMatching.text_matches?(body, text), msg)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
def dom_document_for(actual)
|
|
273
|
+
Dommy::Rails::MatchTarget.document(actual)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def dom_body_for(actual)
|
|
277
|
+
Dommy::Rails::MatchTarget.body(actual)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def form_desc(action:, method:, model:)
|
|
281
|
+
parts = []
|
|
282
|
+
parts << "action=#{action}" if action
|
|
283
|
+
parts << "method=#{method}" if method
|
|
284
|
+
parts << "model=#{model}" if model
|
|
285
|
+
parts.empty? ? "any form" : parts.join(" ")
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def meta_desc(name:, property:, content:)
|
|
289
|
+
parts = []
|
|
290
|
+
parts << "name=#{name}" if name
|
|
291
|
+
parts << "property=#{property}" if property
|
|
292
|
+
parts << "content=#{content}" if content
|
|
293
|
+
parts.empty? ? "matching any criteria" : parts.join(" ")
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dommy/internal/dom_matching"
|
|
4
|
+
require "dommy/internal/element_matching"
|
|
5
|
+
require_relative "url_matcher"
|
|
6
|
+
|
|
7
|
+
module Dommy
|
|
8
|
+
module Rails
|
|
9
|
+
module PageInspector
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def title_matches?(document, expected)
|
|
13
|
+
Dommy::Internal::DomMatching.text_matches?(document.title.to_s, expected, exact: true)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def meta_matches?(document, name: nil, property: nil, content: nil)
|
|
17
|
+
document.query_selector_all("meta").to_a.any? do |meta|
|
|
18
|
+
(name.nil? || meta.get_attribute("name").to_s == name.to_s) &&
|
|
19
|
+
(property.nil? || meta.get_attribute("property").to_s == property.to_s) &&
|
|
20
|
+
(content.nil? || meta.get_attribute("content").to_s == content.to_s)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def csrf_meta_tags?(document)
|
|
25
|
+
param = document.query_selector("meta[name='csrf-param']")
|
|
26
|
+
token = document.query_selector("meta[name='csrf-token']")
|
|
27
|
+
present_content?(param) && present_content?(token)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def authenticity_token?(document)
|
|
31
|
+
document.query_selector_all("input[type='hidden'][name='authenticity_token']").to_a.any? do |input|
|
|
32
|
+
input.get_attribute("value").to_s != ""
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def links(document, text: nil, href: nil)
|
|
37
|
+
Dommy::Internal::ElementMatching.find_links(document, text: text, href: href && UrlMatcher.new(href))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def turbo_frames(document, id = nil, text: nil)
|
|
41
|
+
frames = document.query_selector_all("turbo-frame").to_a
|
|
42
|
+
frames = frames.select { |frame| frame.get_attribute("id").to_s == id.to_s } if id
|
|
43
|
+
frames = frames.select { |frame| Dommy::Internal::DomMatching.text_matches?(frame.text_content, text) } if text
|
|
44
|
+
frames
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def xpath_matches(document, expression, text: nil)
|
|
48
|
+
nodes = document.xpath(expression).to_a
|
|
49
|
+
nodes = nodes.select { |node| Dommy::Internal::DomMatching.text_matches?(node.text_content, text) } if text
|
|
50
|
+
nodes
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def checkable_fields(document, name: nil, checked: nil)
|
|
54
|
+
Dommy::Internal::ElementMatching.find_checkable_fields(document, name: name, checked: checked)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def selects(document, name: nil, label: nil)
|
|
58
|
+
Dommy::Internal::ElementMatching.find_selects(document, name: name, label: label)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def present_content?(element)
|
|
62
|
+
element && element.get_attribute("content").to_s != ""
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../browser_spec"
|
|
4
|
+
require "dommy/rspec/capy_style_matchers"
|
|
5
|
+
|
|
6
|
+
# Opt-in RSpec wiring for browser specs: `require "dommy/rails/rspec/browser"`
|
|
7
|
+
# (e.g. in rails_helper), then tag example groups with `type: :browser` to get
|
|
8
|
+
# the `browser` helper (a javascript: true session over the Rails app) without
|
|
9
|
+
# an explicit `include`. Route URL helpers (`root_path`, …) are included too, so
|
|
10
|
+
# browser specs read like request specs.
|
|
11
|
+
#
|
|
12
|
+
# RSpec.describe "Todos", type: :browser do
|
|
13
|
+
# it "toggles a todo" do
|
|
14
|
+
# browser.visit root_path
|
|
15
|
+
# browser.click "li.todo"
|
|
16
|
+
# expect(browser).to have_css("li.todo.is-completed")
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
if defined?(::RSpec)
|
|
20
|
+
::RSpec.configure do |config|
|
|
21
|
+
config.include Dommy::Rails::BrowserSpec, type: :browser
|
|
22
|
+
|
|
23
|
+
if defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
|
|
24
|
+
config.include ::Rails.application.routes.url_helpers, type: :browser
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# When a matcher fails on a trace-enabled session subject (a browser spec's
|
|
29
|
+
# `expect(browser).to have_text …`), append the current page and a recent
|
|
30
|
+
# trace to the failure message. Subjects without a trace (request/view specs'
|
|
31
|
+
# `expect(dom)`) are left untouched.
|
|
32
|
+
Dommy::RSpec.failure_context = lambda do |subject|
|
|
33
|
+
next nil unless subject.respond_to?(:trace) && subject.trace
|
|
34
|
+
|
|
35
|
+
trace = subject.trace
|
|
36
|
+
page = trace.current_page
|
|
37
|
+
"Current page: #{page[:url]} title=#{page[:title].inspect}\n\n" \
|
|
38
|
+
"Recent trace:\n#{trace.to_text(limit: 15)}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dommy
|
|
4
|
+
module Rails
|
|
5
|
+
module RSpec
|
|
6
|
+
module Integration
|
|
7
|
+
include Dommy::Rails::DomSource
|
|
8
|
+
# Include order matters: Rails::RSpec::Matchers comes last so its
|
|
9
|
+
# Rails-specific `have_link` (URL-normalizing `href:` matching)
|
|
10
|
+
# deliberately overrides the CapyStyleMatchers version.
|
|
11
|
+
include ::Dommy::RSpec::CapyStyleMatchers
|
|
12
|
+
include Dommy::Rails::RSpec::Matchers
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|