how to compare expected value to be in the list [duplicate] - protractor

One of my test expects an error message text to be one of multiple values. Since getText() returns a promise I cannot use toContain() jasmine matcher. The following would not work since protractor (jasminewd under-the-hood) would not resolve a promise in the second part of the matcher, toContain() in this case:
expect(["Unknown Error", "Connection Error"]).toContain(page.errorMessage.getText());
Question: Is there a way to check if an element is in an array with jasmine+protractor where an element is a promise?
In other words, I'm looking for inverse of toContain() so that the expect() would implicitly resolve the promise passed in.
As a workaround, I can explicitly resolve the promise with then():
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
});
I'm not sure if this is the best option. I would also be okay with a solution based on third-parties like jasmine-matchers.
As an example, this kind of assertion exists in Python:
self.assertIn(1, [1, 2, 3, 4])

Looks like you need a custom matcher. Depending on the version of Jasmine you are using:
With Jasmine 1:
this.addMatchers({
toBeIn: function(expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
return possibilities.indexOf(this.actual) > -1;
}
});
With Jasmine 2:
this.addMatchers({
toBeIn: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
var passed = possibilities.indexOf(actual) > -1;
return {
pass: passed,
message: 'Expected [' + possibilities.join(', ') + ']' + (passed ? ' not' : '') + ' to contain ' + actual
};
}
};
}
});
You'll have to execute this in the beforeEach section on each of your describe blocks it's going to be used in.
Your expect would look like:
expect(page.errorMessage.getText()).toBeIn(["Unknown Error", "Connection Error"]);

The alternative solution is to use .toMatch() matcher with Regular Expressions and specifically a special character | (called "or"), which allows to match only one entry to succeed:
expect(page.errorMessage.getText()).toMatch(/Unknown Error|Connection Error/);

To me, the work-around that you identified is the best solution. However, we should not forget that this is an asynchronous execution and you might want to consider Jasmine's asynchronous support.
Then, your test will look like the following one:
it('should check item is in array', function(done){ //Note the argument for callback
// do your stuff/prerequisites for the spec here
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
done(); // Spec is done!
});
});
Note: If you don't pass this done argument to the spec callback, it is going to run to completion without failures, but no assertions are going to be reported in the execution results for that spec (in other words, that spec will have 0 assertions) and it might lead to confusions.

Related

how to prevent logging warning in a .get(true , false) statement to appear even though it is true and not false

I am making an application which rarely uses the terminal for output. So, I found that the logging library was a great way to help debug faulty code as supposed to the print statement.
But, for this code, specifically the .get() statement at the bottom...
def process_variables(self, argument):
data = pd.read_excel(self.url, sheet_name=self.sheet)
data = pd.concat([data.iloc[2:102], data.iloc[107:157]]).reset_index()
fb = data.loc[0:99, :].reset_index()
nfb = data.loc[100:155, :].reset_index()
return {'fb': data.loc[0:99, :].reset_index(),
'nfb': data.loc[100:155, :].reset_index(),
'bi': data.loc[np.where(data['Unnamed: 24'] != ' ')],
'uni': data.loc[np.where(data['Unnamed: 25'] != ' ')],
'fb_bi': fb.loc[np.where(fb['Unnamed: 24'] != ' ')],
'fb_uni': fb.loc[np.where(fb['Unnamed: 25'] != ' ')],
'nfb_bi': nfb.loc[np.where(nfb['Unnamed: 24'] != ' ')],
'nfb_uni': nfb.loc[np.where(nfb['Unnamed: 25'] != ' ')],
}.get(argument, f"{logging.warning(f'{argument} not found in specified variables')}")
...returns this...
output
The output returns the default argument even though the switch-case argument was successful, given that it did return the pandas Data frame.
So how can I make it so it only appears when it wasn't found, as it should if it were just a string and not a logging-string method.
Thank you for your help in advance :)
Python evaluates the arguments for the arguments to a function before it calls the function. That's why your logging function will get called regardless of the result of get(). Another thing is your f-string is probably going to evaluate to "None" every time since logging.warning() doesn't return anything, which doesn't seem like what you intended. You should just handle this with a regular if statement like
variables = {
'fb': data.loc[0:99, :].reset_index(),
...
}
if argument in variables:
return variables[argument]
else:
logging.warning(f'{argument} not found in specified variables')

Pre-compile textual replacement macro with arguments

I am trying to create some kind of a dut_error wrapper. Something that will take some arguments and construct them in a specific way to a dut_error.
I can't use a method to replace the calls to dut_error because to my understanding after check that ... then ... else can only come a dut_error (or dut_errorf). And indeed if I try to do something like:
my_dut_error(arg1: string, arg2: string) is {
dut_error("first argument is ", arg, " and second argument is ", arg2);
};
check that FALSE else my_dut_error("check1", "check2");
I get an error:
*** Error: Unrecognized exp
[Unrecognized expression 'FALSE else my_dut_error("check1", "check2")']
at line x in main.e
check that FALSE else my_dut_error("check1", "check2");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So I thought about defining a macro to simply do a textual replace from my wrapper to an actual dut_error:
define <my_dut_error'exp> "my_dut_error(<arg1'name>, <arg2'name>)" as {
dut_error("first argument is ", <arg1'name>, " and second argument is ", <arg2'name>)
};
But got the same error.
Then I read about the preprocessor directive #define so tried:
#define my_dut_error(arg1, arg2) dut_error("first argument is ", arg, " and second argument is ", arg2)
But that just gave a syntax error.
How can I define a pre-compiled textual replacement macro that takes arguments, similar to C?
The reason I want to do that is to achieve some sort of an "interface" to the dut_error so all errors have a consistent structure. This way, different people writing different errors will only pass the arguments necessary by that interface and internally an appropriate message will be created.
not sure i understood what you want to do in the wrapper, but perhaps you can achieve what you want by using the dut_error_struct.
it has set of api, which you can use as hooks (do something when the error is caught) and to query about the specific error.
for example:
extend dut_error_struct {
pre_error() is also {
if source_method_name() == "post_generate" and
source_struct() is a BLUE packet {
out("\nProblem in generation? ", source_location());
// do something for error during generation
};
write() is first {
if get_mesage() ~ "AHB Error..." {
ahb_monitor::increase_errors();
};
};
};
dut_error accepts one parameter, one string. but you can decide of a "separator", that will define two parts to the message.
e.g. - instruct people to write "XXX" in the message, before "first arg" and "second arg".
check that legal else dut_error("ONE thing", "XXX", "another thing");
check that x < 7 else dut_error("failure ", "XXX", "of x not 7 but is ", x);
extend dut_error_struct {
write() is first {
var message_parts := str_split(get_message(), "XXX");
if message_parts.size() == 2 {
out ("First part of message is ", message_parts[0],
"\nand second part of message is ", message_parts[1]
);
};
};
I could get pretty close to what I want using the dut_errorf method combined with a preprocessor directive defining the format string:
#define DUT_FORMAT "first argument is %s and second argument is %s"
check that FALSE else dut_errorf(DUT_FORMAT, "check1", "check2");
but I would still prefer a way that doesn't require this DUT_FORMAT directive and instead uses dut_error_struct or something similar.

Can i have 2 conditions in protractor expect function? Also give me expect statement to verify whether the getText() has the expected value?

Here i want to combine the below 2 expectations into one.
expect(button.getText()).toEqual('Process Successful');
expect(button.getText().indexOf('- code 3001')).toBeGreaterThan(0);
Also whether the below statement is correct or not. I am trying to verify in the getText() whether expected value is present in the text.
expect(button.getText().indexOf('- code 3001')).toBeGreaterThan(0);
You can use expect().toContain() to verify text contained in string.
expect(button.getText()).toContain('Process Successful');
expect(button.getText()).toContain('- code 3001');
You can also do it in another way,
var buttonContainsText = button.getText().then(function(text){
return (text.indexOf('Process Successful') > -1) && (text.indexOf('- code 3001') > -1)
})
expect(buttonContainsText).toBeTruthy();

How to indiciate a failure for a function with a void result

I have a function in scala which has no return-value (so unit). This function can sometimes fail (if the user provided parameters are not valid). If I were on java, I would simply throw an exception. But on scala (although the same thing is possible), it is suggested to not use exceptions.
I perfectly know how to use Option or Try, but they all only make sense if you have something valid to return.
For example, think of a (imaginary) addPrintJob(printJob: printJob): Unit command which adds a print job to a printer. The job definition could now be invalid and the user should be notified of this.
I see the following two alternatives:
Use exceptions anyway
Return something from the method (like a "print job identifier") and then return a Option/Either/Try of that type. But this means adding a return value just for the sake of error handling.
What are the best practices here?
You are too deep into FP :-)
You want to know whether the method is successful or not - return a Boolean!
According to this Throwing exceptions in Scala, what is the "official rule" Throwing exceptions in scala is not advised as because it breaks the control flow. In my opinion you should throw an exception in scala only when something significant has gone wrong and normal flow should not be continued.
For all other cases it generally better to return the status/result of the operation that was performed. scala Option and Either serve this purpose. imho A function which does not return any value is a bad practice.
For the given example of the addPrintJob I would return an job identifier (as suggested by #marstran in comments), if this is not possible the status of addPrintJob.
The problem is that usually when you have to model things for a specific method it is not about having success or failure ( true or false ) or ( 0 or 1 - Unit exit codes wise ) or ( 0 or 1 - true or false interpolation wise ) , but about returning status info and a msg , thus the most simplest technique I use ( whenever code review naysayers/dickheads/besserwissers are not around ) is that
val msg = "unknown error has occurred during ..."
val ret = 1 // defined in the beginning of the method, means "unknown error"
.... // action
ret = 0 // when you finally succeeded to implement FULLY what THIS method was supposed to to
msg = "" // you could say something like ok , but usually end-users are not interested in your ok msgs , they want the stuff to work ...
at the end always return a tuple
return ( ret , msg )
or if you have a data as well ( lets say a spark data frame )
return ( ret , msg , Some(df))
Using return is more obvious, although not required ( for the purists ) ...
Now because ret is just a stupid int, you could quickly turn more complex status codes into more complex Enums , objects or whatnot , but the point is that you should not introduce more complexity than it is needed into your code in the beginning , let it grow organically ...
and of course the caller would call like
( ret , msg , mayBeDf ) = myFancyFunc(someparam, etc)
Thus exceptions would mean truly error situations and you will avoid messy try catch jungles ...
I know this answer WILL GET down-voted , because well there are too much guys from universities with however bright resumes writing whatever brilliant algos and stuff ending-up into the spagetti code we all are sick of and not something as simple as possible but not simpler and of course something that WORKS.
BUT, if you need only ok/nok control flow and chaining, here is bit more elaborated ok,nok example, which does really throw exception, which of course you would have to trap on an upper level , which works for spark:
/**
* a not so fancy way of failing asap, on first failing link in the control chain
* #return true if valid, false if not
*/
def isValid(): Boolean = {
val lst = List(
isValidForEmptyDF() _,
isValidForFoo() _,
isValidForBar() _
)
!lst.exists(!_()) // and fail asap ...
}
def isValidForEmptyDF()(): Boolean = {
val specsAreMatched: Boolean = true
try {
if (df.rdd.isEmpty) {
msg = "the file: " + uri + " is empty"
!specsAreMatched
} else {
specsAreMatched
}
} catch {
case jle: java.lang.UnsupportedOperationException => {
msg = msg + jle.getMessage
return false
}
case e: Exception => {
msg = msg + e.getMessage()
return false
}
}
}
Disclaimer: my colleague helped me with the fancy functions syntax ...

What's wrong with my Meteor publication?

I have a publication, essentially what's below:
Meteor.publish('entity-filings', function publishFunction(cik, queryArray, limit) {
if (!cik || !filingsArray)
console.error('PUBLICATION PROBLEM');
var limit = 40;
var entityFilingsSelector = {};
if (filingsArray.indexOf('all-entity-filings') > -1)
entityFilingsSelector = {ct: 'filing',cik: cik};
else
entityFilingsSelector = {ct:'filing', cik: cik, formNumber: { $in: filingsArray} };
return SB.Content.find(entityFilingsSelector, {
limit: limit
});
});
I'm having trouble with the filingsArray part. filingsArray is an array of regexes for the Mongo $in query. I can hardcode filingsArray in the publication as [/8-K/], and that returns the correct results. But I can't get the query to work properly when I pass the array from the router. See the debugged contents of the array in the image below. The second and third images are the client/server debug contents indicating same content on both client and server, and also identical to when I hardcode the array in the query.
My question is: what am I missing? Why won't my query work, or what are some likely reasons it isn't working?
In that first screenshot, that's a string that looks like a regex literal, not an actual RegExp object. So {$in: ["/8-K/"]} will only match literally "/8-K/", which is not the same as {$in: [/8-K/]}.
Regexes are not EJSON-able objects, so you won't be able to send them over the wire as publish function arguments or method arguments or method return values. I'd recommend sending a string, then inside the publish function, use new RegExp(...) to construct a regex object.
If you're comfortable adding new methods on the RegExp prototype, you could try making RegExp an EJSON-able type, by putting this in your server and client code:
RegExp.prototype.toJSONValue = function () {
return this.source;
};
RegExp.prototype.typeName = function () {
return "regex";
}
EJSON.addType("regex", function (str) {
return new RegExp(str);
});
After doing this, you should be able to use regexes as publish function arguments, method arguments and method return values. See this meteorpad.
/8-K/.. that's a weird regex. Try /8\-K/.
A minus (-) sign is a range indicator and usually used inside square brackets. The reason why it's weird because how could you even calculate a range between 8 and K? If you do not escape that, it probably wouldn't be used to match anything (thus your query would not work). Sometimes, it does work though. Better safe than never.
/8\-K/ matches the string "8-K" anywhere once.. which I assume you are trying to do.
Also it would help if you would ensure your publication would always return something.. here's a good area where you could fail:
if (!cik || !filingsArray)
console.error('PUBLICATION PROBLEM');
If those parameters aren't filled, console.log is probably not the best way to handle it. A better way:
if (!cik || !filingsArray) {
throw "entity-filings: Publication problem.";
return false;
} else {
// .. the rest of your publication
}
This makes sure that the client does not wait unnecessarily long for publications statuses as you have successfully ensured that in any (input) case you returned either false or a Cursor and nothing in between (like surprise undefineds, unfilled Cursors, other garbage data.