How to write an RSpec matcher that respect's Capybara's within block?
I'm trying to write a custom RSpec matcher to be used in Rails system tests, running under Capybara — the idea is to match text while ignoring certain <span> tags with it.
This is the matcher:
RSpec::Matchers.define :have_cleaned_text do |text|
match do |content|
content.body.include?(text) || content.body.gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
and the HTML body of the page being tested:
<h1>Test Page</h1>
<div id='constraint'>
<p>Clean text</p>
<p>Broken<span class='separator'>|<span>text</p>
</div>
The first two tests pass:
within('#constraint') do
expect(page).to have_cleaned_text('Clean text')
expect(page).to have_cleaned_text('Broken text')
expect(page).not_to have_cleaned_text('Test Page') # fails!
end
…but the third fails, as have_cleaned_text is ignoring the within block and testing against the whole page.
How can I make my matcher respect the within block? I would have expected it to have been passed as content, not the whole page…
ruby-on-rails rspec capybara
add a comment |
I'm trying to write a custom RSpec matcher to be used in Rails system tests, running under Capybara — the idea is to match text while ignoring certain <span> tags with it.
This is the matcher:
RSpec::Matchers.define :have_cleaned_text do |text|
match do |content|
content.body.include?(text) || content.body.gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
and the HTML body of the page being tested:
<h1>Test Page</h1>
<div id='constraint'>
<p>Clean text</p>
<p>Broken<span class='separator'>|<span>text</p>
</div>
The first two tests pass:
within('#constraint') do
expect(page).to have_cleaned_text('Clean text')
expect(page).to have_cleaned_text('Broken text')
expect(page).not_to have_cleaned_text('Test Page') # fails!
end
…but the third fails, as have_cleaned_text is ignoring the within block and testing against the whole page.
How can I make my matcher respect the within block? I would have expected it to have been passed as content, not the whole page…
ruby-on-rails rspec capybara
add a comment |
I'm trying to write a custom RSpec matcher to be used in Rails system tests, running under Capybara — the idea is to match text while ignoring certain <span> tags with it.
This is the matcher:
RSpec::Matchers.define :have_cleaned_text do |text|
match do |content|
content.body.include?(text) || content.body.gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
and the HTML body of the page being tested:
<h1>Test Page</h1>
<div id='constraint'>
<p>Clean text</p>
<p>Broken<span class='separator'>|<span>text</p>
</div>
The first two tests pass:
within('#constraint') do
expect(page).to have_cleaned_text('Clean text')
expect(page).to have_cleaned_text('Broken text')
expect(page).not_to have_cleaned_text('Test Page') # fails!
end
…but the third fails, as have_cleaned_text is ignoring the within block and testing against the whole page.
How can I make my matcher respect the within block? I would have expected it to have been passed as content, not the whole page…
ruby-on-rails rspec capybara
I'm trying to write a custom RSpec matcher to be used in Rails system tests, running under Capybara — the idea is to match text while ignoring certain <span> tags with it.
This is the matcher:
RSpec::Matchers.define :have_cleaned_text do |text|
match do |content|
content.body.include?(text) || content.body.gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
and the HTML body of the page being tested:
<h1>Test Page</h1>
<div id='constraint'>
<p>Clean text</p>
<p>Broken<span class='separator'>|<span>text</p>
</div>
The first two tests pass:
within('#constraint') do
expect(page).to have_cleaned_text('Clean text')
expect(page).to have_cleaned_text('Broken text')
expect(page).not_to have_cleaned_text('Test Page') # fails!
end
…but the third fails, as have_cleaned_text is ignoring the within block and testing against the whole page.
How can I make my matcher respect the within block? I would have expected it to have been passed as content, not the whole page…
ruby-on-rails rspec capybara
ruby-on-rails rspec capybara
edited Nov 18 '18 at 14:12
John Y
asked Nov 18 '18 at 13:45
John YJohn Y
663516
663516
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
In your example page is a Capybara session (which contains its current scope). When you call body (source and html are aliases) on a session it returns the HTML source of the document. Since you're looking for the HTML source of an element you need something like
RSpec::Matchers.define :have_cleaned_text do |text|
match do |session|
session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
Note that a matcher written like that won't have any waiting/retrying behavior, like the Capybara provided matchers, so you need to ensure your page is loaded/stable before using it.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53361565%2fhow-to-write-an-rspec-matcher-that-respects-capybaras-within-block%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
In your example page is a Capybara session (which contains its current scope). When you call body (source and html are aliases) on a session it returns the HTML source of the document. Since you're looking for the HTML source of an element you need something like
RSpec::Matchers.define :have_cleaned_text do |text|
match do |session|
session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
Note that a matcher written like that won't have any waiting/retrying behavior, like the Capybara provided matchers, so you need to ensure your page is loaded/stable before using it.
add a comment |
In your example page is a Capybara session (which contains its current scope). When you call body (source and html are aliases) on a session it returns the HTML source of the document. Since you're looking for the HTML source of an element you need something like
RSpec::Matchers.define :have_cleaned_text do |text|
match do |session|
session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
Note that a matcher written like that won't have any waiting/retrying behavior, like the Capybara provided matchers, so you need to ensure your page is loaded/stable before using it.
add a comment |
In your example page is a Capybara session (which contains its current scope). When you call body (source and html are aliases) on a session it returns the HTML source of the document. Since you're looking for the HTML source of an element you need something like
RSpec::Matchers.define :have_cleaned_text do |text|
match do |session|
session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
Note that a matcher written like that won't have any waiting/retrying behavior, like the Capybara provided matchers, so you need to ensure your page is loaded/stable before using it.
In your example page is a Capybara session (which contains its current scope). When you call body (source and html are aliases) on a session it returns the HTML source of the document. Since you're looking for the HTML source of an element you need something like
RSpec::Matchers.define :have_cleaned_text do |text|
match do |session|
session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
end
end
Note that a matcher written like that won't have any waiting/retrying behavior, like the Capybara provided matchers, so you need to ensure your page is loaded/stable before using it.
answered Nov 18 '18 at 16:56
Thomas WalpoleThomas Walpole
30.9k32849
30.9k32849
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53361565%2fhow-to-write-an-rspec-matcher-that-respects-capybaras-within-block%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown