Check inequality of two inputs in Cypress - unit-testing

I have to check whether a variable is less than a constant value in Cypress. How can we achieve this?
e.g: check whether a given variable is less than 30.

I'm making a few assumptions here, but, something like the following should work.
// define constant
const maxValue = 30;
cy.get('foo') // get element with variable text
.then(($el) => { // use the yielded element in a .then()
// get the text of the element using JQuery's `.text()`
// and compare the value using Chai's `lessThan`.
expect($el.text()).to.be.lessThan(maxValue);
});
References for inline comments:
JQuery's text()
Chai's lessThan (alias for below)

Related

Getting multiple Instances of key using bsearch()

is there a way to implement bsearch() to find multiple instances of key.
for example: (obj*)bsearch(key=r,arr,elements,sizeof(obj),(int(*)(const void*, const void*)bcompare);
The code I currently wrote only finds the first instance and cannot proceed past the first found due to how it works.
getline(target,81);
if(strcmp(target,"exit") == 0 || strcmp(target, "") == 0) break;
p = (Info*)bsearch(target,list,num,sizeof(Info),(int(*)(const void*, const void*))bcompare);
int foundIndex = (int)(p-list);
if(!p){
err_dis1_win();
clrscr();
}
else{
display_record(p);
cout << "\n\n found at index " << foundIndex << "\n";
getch();
clrscr();
}
Variables:
p - is a pointer to object of class Info
target - arr of char
list - arr of obj
foundIndex - index of element found
Info - derived class from base class
**compare function
int bcompare(char *a,Info *b){
return(strncmpi(a, b -> get_name(), strlen(a)));
}
I cannot use other methods such as std::find or writing my own binary search function and have to use bsearch()
I have tried loops inside the else block, and the compare function using the varible foundIndex, as well as using a while loop on the return value looping through the obj list arr. Is there a way to start at a specific index. I appreciate any help. I am not looking for code but a general push in the right direction. Thank you.
Caveat - The current code compiles and runs as expected however, the functionality that I want, cannot be figured out by myself. Google and search on Stackoverflow has not produced an related issue.
Since bsearch() returns only one item, I interpret "find multiple instances of key" as "find the first instance of a key". The caller can then step forward through the array from that item to process each item matching the key, until it reaches the end or reaches an item that does not match.
If you must use the standard library's bsearch() function and persuade it to find the first item matching a given key, then all you really have to work with is the comparison function you present. bsearch() will return an item that matches the key according to that function, but if more than one item matches then there is no guarantee which one will be returned. You must ensure, then, that only the item you want matches.
You can approach that with an appropriate implementation of the comparison function, but there is a significant problem. The function will in some cases need to evaluate the item preceding the one specified to it, but it must not attempt to examine an item preceding the array's first. bsearch() does not itself convey any information about the array bounds to the comparison function.
There are at least two possible solutions, neither of them stellar.
Store the array lower bound in some well-known location that the function can access. For example, if the comparison function is a static member function, then maybe you would use a static variable of its class. But that is not thread-safe. You could do something similar with thread-local variables, but even then it's ugly. Either way, you have to be sure to set that variable appropriately before you call bsearch(), and that's ugly, too.
OR
Ensure that you never bsearch() for the first item. One way you could do that would be by checking preliminarily whether the first item matches (but not via the comparison function), and using it directly instead of calling bsearch() in the event that it does match. I'd wrap that in a method, myself, and if you must not do so then requiring that such a calling discipline be employed manually is also ugly.
Having chosen one of the above, you can implement a comparison function that looks at the previous item's key in addition to the specified item's. Something along these lines (which assumes the second alternative):
struct my_item {
int key;
void *data;
};
// bsearch() passes the target item as the first argument, and the one to compare
// to it as the second
int compare_items(const void *to_find, const void *to_check) {
const struct my_item *to_find_item = (const struct my_item *) to_find;
const struct my_item *to_check_item = (const struct my_item *) to_check;
// Check first how the key members are ordered
if (to_find_item->key < to_check_item->key) {
return -1;
} else if (to_find_item->key > to_check_item->key) {
return 1;
} else {
// The key members match, so check whether we're looking at the first
// such item.
const struct my_item *previous_item = to_check_item - 1;
// If the previous item's key does match, then we know the item we're
// looking for is an earlier one than we are presently checking.
return (previous_item->key == to_check_item->key) ? -1 : 0;
}
}

How to search by member accessor value with std::find_if()?

I am learning C++ at the moment and have an example program implemented with an array of objects data store. To make some other operations easier, I have changed the store to a vector. With this change I am now not sure of the best way to search the store to find an object based on a member accessor value.
Initially I used a simple loop:
vector<Composer> composers; // where Composer has a member function get_last_name() that returns a string
Composer& Database::get_composer(string last_name)
{
for (Composer& c : composers)
if (c.get_last_name().compare(last_name))
return c;
throw std::out_of_range("Composer not found");
}
This works just fine of course, but to experiment I wanted to see if there were vector specific functions that could also do the job. So far I have settled on trying to use find_if() (if there is a better function, please suggest).
However, I am not sure exactly the correct way to use find_if(). Based on code seen in online research I have replaced the above with the following:
vector<Composer> composers; // where Composer has a member function get_last_name() that returns a string
Composer& Database::get_composer(string last_name)
{
auto found = find_if(composers.begin(), composers.end(),
[last_name](Composer& c) -> bool {c.get_last_name().compare(last_name);});
if (found == composers.end())
throw out_of_range("Composer not found");
else
return *found;
}
This does not work. It does find a result, but it is the incorrect one. If an argument that matches, say the third composer's last name the function always returns the first item from the vector (if I pass an argument that doesn't match any last name the function correctly throws an exception)... what am I doing wrong?
You are on the right track, your lambda needs return statement. Also in such case you do not have to specify it's return type explicitly, it can be deduced:
find_if(composers.begin(), composers.end(),
[last_name](const Composer& c) { return c.get_last_name() == last_name);});
you original code should not compile or at least emit warning(s), you should pay attention to them.
Note: it is not clear how your original code worked if you tested it, it should be:
if (c.get_last_name().compare(last_name) == 0 )
or simply:
if (c.get_last_name() == last_name )
as std::string::compare() returns int -1 0 or 1, so your code searches for string that does not match variable last_name
With range-v3, you may use projection:
auto it = ranges::find(composers, last_name, &composers::get_last_name);

How to retrieve value from a map in c++

I have a map with some values. Then I have a function that returns some string, and this string will be a member of the keys in map. I need to retrieve the value based on the key and pass it to another function, which takes it as argument.
map<string,int> SymbolTable;
SymbolTable["R0"]=0;
SymbolTable["R1"]=1;
SymbolTable["R2"]=2;
SymbolTable["R3"]=3;
string value=getValue(); //this one will return something from R0 to R3
nextFunction(SymbolTable[value]); // this part is wrong
If I give value=="R0" or some static value, this is working as expected. But whenever I pass this dynamic value, it returns 0 always, so my nextFunction is taking 0 as argument.
I tried to output the return value from getValue() to check what it is returning, and it is correct. I have tried this and similar ways, but all gives me the same issue. Can someone guide me on what am I doing wrong here? TIY
If I give value=="R0" or some static value, this is working as
expected. But whenever I pass this dynamic value, it returns 0 always
It simply means the "dynamic value" you obtained does not exist as a key in the map. std::map's operator [] inserts a default constructed value if the associated key does not exist.
To check for the existence of value in your map, you can do:
string value=getValue();
if(SymbolTable.count(value)){
//key exists....
nextFunction(SymbolTable[value]); // this part should be correct now
}
or you can equally use std::map::find

find an integer in a double map container

I wanted to know if there was a way to find an int in a double type map container. For instance in the following example
std::map<double,double> mt;
mt[2.33] =3.45;
if(mt.find(2)!=mt.end()) //How to do a search for an int instead of a map
{
//Found
}
I wanted to know if there was a way to tell the map to search for an int instead of a double. Since the map would search for a double by default.
One way you can do this is to use lower_bound/upper_bound member functions to get a range of values around your integer, and then check this range manually.
Other way is to use a map with custom comparator that compares keys as integers (see std::map referernce), so you preserve initial key values and can search for integers. But you can't search for doubles then.
Anyways, the task is a bit strange, you probably should reconsider your data structures choice for your problem.
The following should work:
it = mt.lower_bound(2);
However, you need to check the item afterwards;
it->first<3;
must yield true for correct result.
if you are interested only in the integral part (or anything else, as you can use a lambda for that), you might use
auto result = find_if(begin(mt), end(mt),
[&](pair<double, double> p){return (int)(p.first) == 2)}
)
if (result != mt.end())
{
// do your stuff
}
The use case for such a kind of approach still remains unclear...

How do you use ranges in D?

Whenever I try to use ranges in D, I fail miserably.
What is the proper way to use ranges in D? (See inline comments for my confusion.)
void print(R)(/* ref? auto ref? neither? */ R r)
{
foreach (x; r)
{
writeln(x);
}
// Million $$$ question:
//
// Will I get back the same things as last time?
// Do I have to check for this every time?
foreach (x; r)
{
writeln(x);
}
}
void test2(alias F, R)(/* ref/auto ref? */ R items)
{
// Will it consume items?
// _Should_ it consume items?
// Will the caller be affected? How do I know?
// Am I supposed to?
F(items);
}
You should probably read this tutorial on ranges if you haven't.
When a range will and won't be consumed depends on its type. If it's an input range and not a forward range (e.g if it's an input stream of some kind - std.stdio.byLine would be one example of this), then iterating over it in any way shape or form will consume it.
//Will consume
auto result = find(inRange, needle);
//Will consume
foreach(e; inRange) {}
If it's a forward range and it's a reference type, then it will be consumed whenever you iterate over it, but you can call save to get a copy of it, and consuming the copy won't consume the original (nor will consuming the original consume the copy).
//Will consume
auto result = find(refRange, needle);
//Will consume
foreach(e; refRange) {}
//Won't consume
auto result = find(refRange.save, needle);
//Won't consume
foreach(e; refRange.save) {}
Where things get more interesting is forward ranges which are value types (or arrays). They act the same as any forward range with regards to save, but they differ in that simply passing them to a function or using them in a foreach implicitly saves them.
//Won't consume
auto result = find(valRange, needle);
//Won't consume
foreach(e; valRange) {}
//Won't consume
auto result = find(valRange.save, needle);
//Won't consume
foreach(e; valRange.save) {}
So, if you're dealing with an input range which isn't a forward range, it will be consumed regardless. And if you're dealing with a forward range, you need to call save if you want want to guarantee that it isn't consumed - otherwise whether it's consumed or not depends on its type.
With regards to ref, if you declare a range-based function to take its argument by ref, then it won't be copied, so it won't matter whether the range passed in is a reference type or not, but it does mean that you can't pass an rvalue, which would be really annoying, so you probably shouldn't use ref on a range parameter unless you actually need it to always mutate the original (e.g. std.range.popFrontN takes a ref because it explicitly mutates the original rather than potentially operating on a copy).
As for calling range-based functions with forward ranges, value type ranges are most likely to work properly, since far too often, code is written and tested with value type ranges and isn't always properly tested with reference types. Unfortunately, this includes Phobos' functions (though that will be fixed; it just hasn't been properly tested for in all cases yet - if you run into any cases where a Phobos function doesn't work properly with a reference type forward range, please report it). So, reference type forward ranges don't always work as they should.
Sorry, I can't fit this into a comment :D. Consider if Range were defined this way:
interface Range {
void doForeach(void delegate() myDel);
}
And your function looked like this:
void myFunc(Range r) {
doForeach(() {
//blah
});
}
You wouldn't expect anything strange to happen when you reassigned r, nor would you expect
to be able to modify the caller's Range. I think the problem is that you are expecting your template function to be able to account for all of the variation in range types, while still taking advantage of the specialization. That doesn't work. You can apply a contract to the template to take advantage of the specialization, or use only the general functionality.
Does this help at all?
Edit (what we've been talking about in comments):
void funcThatDoesntRuinYourRanges(R)(R r)
if (isForwardRange(r)) {
//do some stuff
}
Edit 2 std.range It looks like isForwardRange simply checks whether save is defined, and save is just a primitive that makes a sort of un-linked copy of the range. The docs specify that save is not defined for e.g. files and sockets.
The short of it; ranges are consumed. This is what you should expect and plan for.
The ref on the foreach plays no role in this, it only relates to the value returned by the range.
The long; ranges are consumed, but may get copied. You'll need to look at the documentation to decide what will happen. Value types get copied and thus a range may not be modified when passed to a function, but you can not rely on if the range comes as a struct as the data stream my be a reference, e.g. FILE. And of course a ref function parameter will add to the confusion.
Say your print function looks like this:
void print(R)(R r) {
foreach (x; r) {
writeln(x);
}
}
Here, r is passed into the function using reference semantics, using the generic type R: so you don't need ref here (and auto will give a compilation error). Otherwise, this will print the contents of r, item-by-item. (I seem to remember there being a way to constrain the generic type to that of a range, because ranges have certain properties, but I forget the details!)
Anyway:
auto myRange = [1, 2, 3];
print(myRange);
print(myRange);
...will output:
1
2
3
1
2
3
If you change your function to (presuming x++ makes sense for your range):
void print(R)(R r) {
foreach (x; r) {
x++;
writeln(x);
}
}
...then each element will be increased before being printed, but this is using copy semantics. That is, the original values in myRange won't be changed, so the output will be:
2
3
4
2
3
4
If, however, you change your function to:
void print(R)(R r) {
foreach (ref x; r) {
x++;
writeln(x);
}
}
...then the x is reverted to reference semantics, which refer to the original elements of myRange. Hence the output will now be:
2
3
4
3
4
5