Simplifying an xpath expression used by selenium - xpath

I've got the following XPath expression that I call from selenium (technically, from splinter, which is calling selenium):
//label[text()="data"]/following-sibling::div/input|//label[text()="data"]/following-sibling::div/textarea
Is there a way to simplify this expression? The following doesn't work in selenium, although it seems to work in AquaPath:
//label[text()="data"]/following-sibling::div/(input|textarea)

Try:
//label[text()="data"]/following-sibling::div/*[self::input or self::textarea]
Whenever there are many (more than 3 alternatives), an expression like this is considerably shorter:
someExpr/*[contains('|name1|name2|name3|name4|', concat('|',name(), '|'))]

Related

Using [] with the Safe Navigation Operator in Ruby

I currently have a piece of code that looks like:
if match = request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)
match[:slug]
end
Is there a way to use the safe navigation operator (introduced in 2.3.0) to avoid this if conditional?
Just use the ordinary (non-sugar) form.
request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.[](:slug)
For better readability I would pick #dig instead of the #[].
Like,
request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.dig(:slug)
instead of
request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.[](:slug)
For readability, I prefer using the match's named_captures method which is available from ruby 1.9.1, with the safe operator which is available from ruby 2.3.0.
request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.named_captures&.dig('slug')
You can send any method, so using safe-browsing operator this will be:
request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.send(:[], :slug)

Negate argument matcher in RSpec 3

I have a function I'm calling that I need to test the arguments of. Normally I'd do something like:
expect(my_obj).to_receive(:my_function).with(include('good_value'))
Is there a way to flip this around, though, to be something like
expect(my_obj).to_receive(:my_function).with(exclude('bad_value'))
In a spec on a return value this is simply accomplished using to_not, but that form of negation is not available when matching arguments it seems. I can find nothing in the docs suggesting a way to do this other than writing a custom matcher, which feels like overkill here.
Is there a simple way I can do this without having to write a custom matcher?
RSpec 3.1+ allows you to define a negated version of any matcher using RSpec::Matchers.define_negated_matcher:
RSpec::Matchers.define_negated_matcher :exclude, :include
Once you've done that, this should work:
expect(my_obj).to_receive(:my_function).with(exclude('bad_value'))
You may try:
http://www.rubydoc.info/gems/rspec-mocks/RSpec/Mocks/ArgumentMatchers#hash_excluding-instance_method
expect(object).to receive(:message).with(hash_excluding(:key => val))

Ruby evaluate without eval?

How could I evaluate at mathematical string without using eval?
Example:
mathstring = "3+3"
Anyway that can be evaluated without using eval?
Maybe something with regex..?
You must either or eval it, or parse it; and since you don't want to eval:
mathstring = '3+3'
i, op, j = mathstring.scan(/(\d+)([+\-*\/])(\d+)/)[0] #=> ["3", "+", "3"]
i.to_i.send op, j.to_i #=> 6
If you want to implement more complex stuff you could use RubyParser (as #LBg wrote here - you could look at other answers too)
I'm assuming you don't want to use eval because of security reasons, and it is indeed very hard to properly sanitize input for eval, but for simple mathematical expressions perhaps you could just check that it only includes mathematical operators and numbers?
mathstring = "3+3"
puts mathstring[/\A[\d+\-*\/=. ]+\z/] ? eval(mathstring) : "Invalid expression"
=> 6
You have 3 options:
In my honest opinion best - parse it to Reverse Polish Notation and then parse it as equation
As you say use RegExps
Fastest, but dangerous and by calling eval but not Kernel#eval
RubyVM::InstructionSequence.new(mathstring).eval
Sure--you'd just want to somehow parse the expression using something other than the bare Ruby interpreter.
There appear to be some good options here: https://www.ruby-toolbox.com/search?q=math
Alternatively, it probably wouldn't be that hard to write your own parser. (Not that I've seriously tried--I could be totally full of crap.)
Dentaku seems (I haven't used it yet) like a good solution - it lets you check your (mathematical and logical) expressions, and to evaluate them.
calculator = Dentaku::Calculator.new
calculator.evaluate('kiwi + 5', kiwi: 2)

In XPath is it possible to use the OR operator with node names?

With XPath, I know that you can use the union operator in the following way:
//*[#id="Catalog"]/thead | //*[#id="Catalog"]/tbody
This seems to be a little awkward to me though. Is there a way to do something similar to one of these instead?
//*[#id="Catalog"]/(thead|tbody)
//*[#id="Catalog"]/(thead or tbody)
//*[#id="Catalog"]/*[nodename="thead" or nodename="tbody"]
That seems a lot more readable and intuitive to me...
While the expression:
//*[#id="Catalog"]/*[name()="thead" or name()="tbody"]
is correct
This expression is more efficient:
//*[#id="Catalog"]/*[self::thead or self::tbody]
There is yet a third way to check if the name of an element is one of a specified sequence of strings:
//*[#id="Catalog"]/*[contains('|thead|tbody|',concat('|',name(),'|'))]
Using this last technique can be especially practical in case the number of possible names is very long (of unlimited and unknown length). The pipe-delimited string of possible names can even be passed as an external parameter to the transformation, which greatly increases its generality, re-usability and "DRY"-ness.
You are looking for the name() function:
//*[#id="Catalog"]/*[name()="thead" or name()="tbody"]
Note that with XPath 2.0 your attempt //*[#id="Catalog"]/(thead|tbody) is correct. That approach does not work however with XPath 1.0.
Yes you can use:
//*[#id="Catalog"]/[nodename='thead' or nodename='tbody']
EDIT:
Just re-read your original post and realised what you were asking. The above syntax wouldn't be correct for this situation. Not sure how to get the name of the node to use but nodename isn't right...

NUnit: What is the most concise way to assert whether an IEnumerable contains an object of a certain type?

I have a method named RenderContent which returns object[]
In my unit test, I need to assert that this array does not contain any objects of type VerifyRequest
At the moment, I'm using the following Assert statement. Is there anything more concise?
Assert.That(
domain.RenderContent().OfType<VerifyRequest>().Count(),
Is.EqualTo(0)
);
I prefer to use fluent syntax. Note also that RenderContent returns object[], not IQueryable<object>.
If you are using NUnit 2.5, you could use something like:
Assert.That(domain.RenderContent(), Has.None.InstanceOf<VerifyRequest>());
But I'm not sure if other unit test frameworks support this assert-style.
Although I don't know the exact NUnit syntax for IsFalse assertion, the best fit for this kind of test is the Any extension method:
Assert.IsFalse(domain.RenderContent().OfType<VerifyRequest>().Any());
It might be tempting to use the Count method, but Any is more efficient, as it will break on the first occurrence.
The Any extension method, which can be given a lambda expression:
Assert.IsFalse(domain.RenderContent().Any(i => i is VerifyRequest));
You could shorten it a tad by using the Assert.AreEqual method instead:
Assert.AreEqual(domain.RenderContent().OfType<VerifyRequest>().Count(), 0);
I prefer the Assert.AreEqual approach; NUNit uses Assert.That for the internal Assert, STringAssert, etc objects. I like just doing Assert.AreEqual(0, domain.RenderContent().OfType().Count()); to check for the counts.
This way, it checks directly that no objects of a type have any number of records, but to a point the variations you see are preference and they all are equally valid. You have to choose what you like for your style of development.

Resources