Test if text does not contain any HTML - capybara

I want to test whether some content does not contain any HTML. What is a simple and clean way to do so?
page.find(".description").should_not have_content /\<.*\>/
Does not work properly, since it fails on <strong>Lorem but passes on <strong>Lorem. Probably due to the way capybara helps its user with escaping HTML.
Solving with xpaths works, but leaves me wondering if there is not a much simpler solution.
page.should_not have_selector(:xpath, "//div[#class="description"]/*")
Is there a built-in way to detect wether some text has been stripped of HTML in Capybara?

Capybara's has_content? (and thus have_content) method aims to inspect text rendered to the user, not text in html source of an element as you expect.
Thus, I think Capybara's behavior is correct:
If html source of .description is <strong>Lorem, user sees <strong>Lorem. Capybara searches this text for /\<.*\>/ and finds it.
If html source of .description is <strong>Lorem, user sees Lorem. Capybara searches this text for /\<.*\>/ and doesn't find it.
If you want to inspect source html of an element, you can use javascript's function innerHTML:
source_text = page.evaluate_script("document.querySelector('.description').innerHTML")
source_text.should_not =~ /\<.*\>/

Related

Capybara - assert against string containing HTML entities?

In a page on my Rails 6 app, I have table cells rendered from the database, and sometimes the text in them is rendered with converted fancy quotes or other HTML entities encoded by our own t method, which does this:
def t(sanitize = true)
Textile.textilize_without_paragraph_safe(self, false, sanitize)
end
It's used like this:
<span class="current_notes"><%= key.notes.t %></span>
So a stored string like Doesn't, pulled from the db, is converted by Textile to Doesn’t and rendered in the page as Doesn’t. Of course, testing the db value against the output of the page fails, because the quote has been converted.
expected to find visible css "#key_notes_135836989 span.current_notes" with text
"Doesn't get used very often." within #<Capybara::Node::Element> but there were no matches.
Also found "Doesn’t get used very often.", which matched the selector but not all filters.
It also fails if I test against the db value, encoded with t, because that contains the HTML entity, not the special character:
expected to find visible css "#key_notes_135836989 span.current_notes" with text
"Doesn’t get used very often." within #<Capybara::Node::Element> but there were no matches.
Also found "Doesn’t get used very often.", which matched the selector but not all filters.
If I assert against CGI.unescapeHTML(string.t), Capybara finds them equivalent.
assert_selector("#key_notes_#{marys_key.id} span.current_notes",
text: CGI.unescapeHTML(marys_key.notes.t))
My question is, since Capybara is always testing against rendered HTML, it seems like there must be an easier way to do this? I can't imagine using CGI.unescapeHTML every time i have some fancy text on the page (it's everywhere in this app).

Capybara not seeing updates to the DOM made by Javascript

I'm running Rails 5.x, with, Cucumber, Siteprism and Capybara through chromedriver. Most things work except..
I have a tiny bit of javascript that changes the class on an element in response to an event. But Capybara never sees the change. It only ever sees the class the element has when the page initially loaded.
Using Chrome, and debugging my Cucumber steps, I can see the element has the new class, but Capybara doesn't see it.
This must be an issue other people have encountered and solved, though I can't find the right subject title.
example coffeescript
$(document).on('focus', 'tbody#item-entry > tr > td > input', (e) ->
$(#).closest('tr').addClass('focused-row')
$(#).closest('td').addClass('focused-cell')
)
example html after the focus event has been triggered
<tr class="focused-row">
<td>ignore this </td>
</tr>
The purpose is to change the background colour of the row containing an input element that has focus. It works.
But Capybara, can't see the class, but it can see any classes added when the page is loaded. e.g.
expect(siteprism_stuff.root_element['class']).to match(/focused-row/)
Ignore the SitePrism stuff, that just gets the right element. root_element is the Capybara class for the dom node.
Now I know it's getting the right Capybara element because if I change my view to put stuff in the class for each row, then it sees that perfectly OK. What it can't see is the any new class added via Coffeescript. Although it's visible in the Chrome inspector, and changes the background color of the focused row as required.
You're specifying an "ends with" CSS attribute selector ($=)
input[class$='form-control']
which since the class attribute for the element you're interested in
<input type="search" class="form-control form-control-sm" placeholder="" aria-controls="universitiesTable">
doesn't end with 'form-control' is correctly not matching. You probably just want to use a normal CSS class selector input.form-control if continuing to do it the way you are. Any of the following options should find the search field and fill in the data you are trying to fill in.
fill_in 'Search:', with: string
fill_in type: 'search', with: string
find(:field, type: 'search').set(string)
find('input.form-control').set(string)
Note: Your question is still unclear as to whether you are seeing the class added in the inspector in test mode, and whether the line color is changing while the tests are running (or whether you're only seeing that in dev mode) - This answer assumes the JS is actually running in test mode and you're seeing the line color change while the tests are running.
You don't show how you're actually triggering the focus event but I'll assume you're clicking the element. The thing to understand when working with Capybara is that the browser works asynchronously, so when something like click has been done, the actions triggered by that click have not necessarily been done yet. Because of that, whenever doing any type of expectation with page elements you should always be using the matchers provided by Capybara rather than the basic matchers provided by RSpec. The Capybara provided matchers include waiting/retrying behavior to handle the asynchronous nature of dealing with the browser. In this case, assuming siteprism_stuff.root_element is the row element then you could be doing something like
expect(siteprism_stuff.root_element).to match_css('.focused-row')
or depending on exactly how your siteprism page objects are setup you could pass the class option to the siteprism existence checker
# `page_section` and `have_row` would need to be replaced with whatever is correct for your site prism page object
expect(page_section).to have_row(class: ['.focused-row'])

Testing for italics with Capybara

Could anyone suggest the best way to look for italics on a page with capybara. I have a feature test that searches for a specific piece of text within a page. This text is in italics and is also a different colour from everything else on the page. I thought looking for italics would be preferable to searching for a colour value but i am unsure how to do either.
<div class="text-control">
<p class="body">Test text is here and then<i>italics</i> are there</p>
</div>
The feature test is written as follows:
Then(/^the word should be highlighted in the example sentence$/) do
end
It sounds like just need to check that the sentence, the p element, contains the word, the i element. To do this you can do:
# Get the element containing the sentence
sentence_element = find('p.body')
# Check that the sentence includes the italics element with a specific text
expect(sentence_element).to have_css('i', text: 'italics')
Assert a text is present in the particular element, sounds reasonable... you can do that using the suggesting by Justin...
Test a text is in italic... that's not a test you want to add in this layer of testing or in any layer in fact...

multi line tag in grails or html

With a grails app and from a local database, I'm returning some text in a xml format.
I can return it well formed in a <textarea></textarea> tag with the correct indenting (tabulation, line return,...etc.)
I want to go a bit further. In the text I'm returning, there are some <img/> tags and I'd like to replace those tag by the real images themselves.
I searched around and found no solution as of now. I understood that you can't add an image to a textarea (other then in a background), and if I choose a div tag, I won't have the indenting anymore (and therefore, harder to read)
I was wondering if using a <g:textField/> or an other tag from the grails library will do the trick. And if so, How can I append them to a page using jquery.
For example, how to append a <g:textField/> in jquery. It doesn't interpret it and I get this error
SyntaxError: missing ) after argument list [Break On This Error]...+doc).append("<input type="text" id="FTMAP_"+nb_sec+"" ...
And in my javascript file, I have
$("#FTM_"+doc).append("<g:textField id='FTMAP_"+nb_sec+"' ... />
Any possible solutions ?
EDIT
I did forget to mention that my final intentions are to be able to modify the text (tags included) and to have a nice and neat indentation so that it is the easiest possible for the end user.
You are asking a few different questions:
1. Can I use a single HTML tag to include images inside pre-formatted text.
No. You will have to parse the text and translate it into styled text yourself.
2. Is there a tag in the grails standard tags to accomplish this for me?
No.
3. How can I add grails tags from my javascript code.
Grails tags are processed on the server-side, and javascript is processed on the client. This means you cannot directly add grails tags via javascript.
There are a couple methods that can accomplish the same result, however:
You can set a javascript variable to the rendered content of a grails tag. This solution is good for data that is known at the time of the initial request.
var tagOutput = "${g.textField(/* etc */)}";
You can make an ajax request for the content to be added. Then your server-side grails code can render the tags you need. This is better for realtime data, or data that will be updated more than once on a single rendered page.

Rails]Using Markdown Markup Language

In my rails application, people are supposed to submit "posts." However, in the default scaffolding, there are some problems in the text input: not allowed HTML code, changing the line doesn't work, etc. From what I've learned, I need to use a markdown-markup language to solve this issue. Is there a guide for me to follow to apply such language to solve my problem?
UPDATE: Here are my problems.
1) Every sentence is combined into one line even if I put a line space.
first line
second line
becomes
first line second line
2) I can't make text bold, italicized, or hyperlink. Like in stackoverflow, user should easily put <b> and make bold text, ** to make italicized, etc. And URL address should automatically be translated to href link.
To do these, I thought I had to use markdown library. I could be mistaken, so I needed someone to guide me through. Railscasts on Markdown
Well, yes, new lines in HTML have no meaning. You need to replace line breaks with <br> to preserve them in HTML. To automatically highlight links, you need to look for links in the text and wrap them in appropriate <a> tags. Finally, if you're not filtering HTML tags, they should still be in there. It all depends on what you're doing. Markdown is something entirely different, a special markup language that enables you to do the above while being easier to write than HTML. It depends on what you want to use.

Resources