angular.copy issue with Jasmine Test case - testing

Request you to help me find the solution of below issue.
I have one function and corresponding Jasmine test case, like the one written below.
If I use angular.copy (and I have to use this only) in my function, Jasmine test case fails and error shown is expected 'originalValue' to equal 'newValue'.
If I use var obj = param1 (and not angular.copy) then Jasmine test case executes successfully.
I have to use angular.copy and at the same time, want jasmine test case to pass. Please help.
function
function func(param1, param2, condition)
{
var obj = angular.copy(param1);
if(condition){
obj.prop = param2;
}
}
jasmine test case
it('xxxx', function(){
var param = {'prop': ''};
var obj = {'prop': 'orignialValue'};
func(param, 'newValue', true);
expect(obj.prop).toEqual('newValue');
});

The example you provided is incorrect.
it('xxxx', function(){
var obj = {'prop': 'orignialValue'};
func(param, 'newValue', true);
expect(obj.prop).toEqual('newValue');
});
param is not defined over here, this should be obj I assume.
Since you use angular.copy, obj.prop is not added by ref to param1.

I found the solution. Instead of doing angular.copy inside the function func, I am first doing angular.copy and then passing this copied object to function func as its first parameter (param1).

Related

Xunit test SerializableError return object value

I am writing unit tests of controller logic with Xunit.
One of my controller actions returns a BadRequestObjectResult with the ModelStateDictionary object:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
To do this my test case adds a ModelState error like this:
controller.ModelState.AddModelError("Test", "This is a test model error");
In the Assert statements of my test case I am checking the return object which is type SerializableError:
var returnError = Assert.IsType<SerializableError>(objectResult.Value);
Assert.Single(returnError);
Assert.True(returnError.ContainsKey("Test"));
Assert.True(returnError.ContainsValue("This is a test model error"));
The Assert.Single(returnError); and Assert.True(returnError.ContainsKey("Test")); checks pass successfully as expected.
However, the check on the check of the error value fails (it returns false but I expect it to return true):
Assert.True(returnError.ContainsValue("This is a test model error"));
I can see from debugging that the Value seems to be nested in an extra string object:
But I have been unable to write a test which tests the value. How do I do it?
As mentioned in another answer, value of Dictionary is an array, so you should address that in the assertions.
var returnError = Assert.IsType<SerializableError>(objectResult.Value);
var errors = objectResult.Value as SerializableError;
Assert.Single(errors);
Assert.True(errors.ContainsKey("Test"));
var errorValues = returnError["Test"] as string[];
Assert.Single(errorValues);
Assert.True(errorValues.Single() == "This is a test model error");
Because SerializableError inherits from Dictionary, you should be able to do it in clearer way with help of FluentAssertions library
var expected = new SerializableError
{
{ "Test", new[] {"This is a test model error"}},
};
objectResult.Value.Should().BeOfType<SerializableError>();
objectResult.Value.Should().BeEquivalentTo(expected);
Your value is a list. so Value[0] or Value.First(). It' a keyvaluepair so you should be able to access it by returnError[keyName].
You need to cast the response to ObjectResult see below
var result = response.Result as BadRequestObjectResult
or
var result = response.Result as OkObjectResult
now you can access the value using result.Value property

javascript function is not recognized as javascript code

I have the following javascript file MyService.js:
function(config) {
config.MyService = function(request) {
return call('classpath:path/to/my.feature#tag', request);
};
return config;
}
I load this js from my karate-config.js in order to reuse it from my feature files.
config = karate.callSingle('classpath:path/to/MyService.js', config);
It works as expected and I can call my.feature from any feature file. For example:
Given def res = call MyService myRequest
The problem appears when I try to add a new level to MyService.js function:
function(config) {
config.ApiOauthService = {
myCall : function(request) {
return call('classpath:path/to/my.feature#tag', request);
}
};
return config;
}
When I add the following code to my feature file:
Given def myCall = call MyService.myCall myRequest
I get the following error: "not a js function or feature file"
Do anybody know where is the problem? Is it possible to do what I am trying to do?
Thanks
Yes in Karate 0.9.3 onwards we have limited JS function nesting to only the top-level. You can find a full explanation in this comment.
So if you need JS function "name spacing" you can easily achieve this as per the documentation: https://github.com/intuit/karate#multiple-functions-in-one-file
And if you need more complex nesting, switch to using Java code where you can nest functions at any level.

Javascript code not working after upgrade to karate 0.9.3

The below function in feature files was working for version 0.9.2. Upgraded to 0.9.3 and this gives error : javascript function call failed: Index: 0.0, Size: 0. Code below:
var cnd = ['test1','test2'];
function set_filter(arg)
{
var i;
var filter = {filterValues:[]};
for(i=0;i<arg.length;i++)
{
filter.filterValues[i] = arg[i];
}
return filter;
}
set_filter(cnd)
Also i was earlier able to push values in a javascript array using below, but this has also stopped working in 0.9.3. Get error:javascript function call failed: TypeError: arr.push is not a function
var arr = [];
arr.push('test1','test2');
Try the scenario below that works in 0.9.2 but reports error (mentioned above) in 0.9.3
Scenario: JS test
* def filter_template =
"""
function() {
var filter_params = {
filterValues:[]
};
return filter_params;
}
"""
* def template = call filter_template
* def filter_condition = ['test1','test2']
* def setFilter =
"""
function(arg) {
var i;
var filter = arg.filter_template;
for(i=0;i<arg.condition.length;i++)
{
filter.filterValues[i] = arg.condition[i];
}
return filter;
}
"""
* def getFilter = call setFilter { filter_template: '#(template)', condition: '#(filter_condition)' }
* print getFilter
Help is much appreciated.
We've made the JS conversions stricter, everything will be a Java collection behind the scenes. If you make this change, things will start working:
filter.filterValues.set(i, arg.condition.get(i));
The same goes for push() - use add() or karate.appendTo(varname, value) instead.
My strong recommendation is don't use too much of JS logic especially loops. Karate has functions such as map(), forEach() and repeat() to solve for these needs. Please refer the docs here: https://github.com/intuit/karate#loops
You will thank me later because it will make your scripts easier to understand and maintain. One reason why this is needed is to pave the way for us to change the JS engine in the future.

how to pass dynamic arguments into functions , instead of hardcoded strings

We are facing an issue while trying to pass argument stored in var .
The issue is we are storing the dynmically retrived div id in a variable and then passing it to .moveToObject function.
But the function throws back error ;
Error: invalid selector: No selector specified
Wanted to know how we can pass arguments stored in variables into various functions.
For instance in the code below , we are retiring sectionId via execute , storing it in sectionId variable .
then using it later on in moveToObject.
all functions seems to work when we are giving arguments inside "" quotes, but in our case we cannot do this. Please help us out how we can achieve this.
it('drag and drop should work', function() {
var sectionId = "";
// load page, then call function()
return driver
.url('http://localhost:9000')
.pause(7000)
.click('#layoutWizardButton')
.click('#tableWizardBuild')
.pause(3000)
.execute(function() {
sectionId = window.document.getElementById('Section1');
}
.moveToObject('#ribbon-radio-tile')
.buttonDown()
.moveToObject(sectionId) -- -- > errors out here
.buttonUp()
.pause(2000)
.end()
});
Try .moveToObject(sectionId.value)

dojo.requireIf does not allow local variables

I've been trying to use dojo.require(If) with a local variable to dynamically load a module on a page based on a condition.
// note: dojo v1.4
djConfig = {
debugAtAllCosts: true
};
Example 1 (does not work):
(function() {
var nameOfClass = "Two";
dojo.require("my.namespace." + nameOfClass);
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
Error: ReferenceError: nameOfClass is not defined.
Example 2 (does not work):
(function() {
var nameOfClass = "Two";
dojo.requireIf(nameOfClass == "One", "my.namespace.One");
dojo.requireIf(nameOfClass == "Two", "my.namespace.Two");
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
Error: ReferenceError: nameOfClass is not defined.
Example 3 (works):
(function() {
window.nameOfClass = "Two";
dojo.requireIf(window.nameOfClass == "One", "my.namespace.One");
dojo.requireIf(window.nameOfClass == "Two", "my.namespace.Two");
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
For some reason, it appears as though require and requireIf only allow global variables inside them. Is that a current limitation, or am I just doing something wrong?
Update 1:
Therefore, if I understand you (#Maine, #jrburke) correctly, this is a limitation of the debugAtAllCosts? If the above code is built as cross-domain (adding the xd file prefix / suffix) and is executed -- it will work as expected?
If that is the case, then what is the proper way of locally testing code that will be executed as cross-domain, without making the actual build?
That also makes me question the motivation for pre-parsing the dojo.require(s). If the loader_xd will not (or rather can not) pre-parse, why is the method that was created for testing/debugging doing so?
Update 2:
Since the two questions in the Update 1 above are not closely related to this one, I've moved them out into a separate discussion.
This is because requireIfs are parsed with regexps as the very first thing, and executed before the normal program flow.
If you'll grep Dojo source for requireIf, you should find this kind of lines handling it (loader_xd.js):
var depRegExp = /dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg;
The condition is then executed with eval in global scope, and not as a part of normal flow.
To clarify more of what Main said, this is an issue with the XD loader in Dojo. debugAtAllCosts: true uses the XD Loader. If you just use the normal Dojo loader without debugAtAllCosts, it is not an issue. Also, attaching the module module name as a property on a publicly visible module would also avoid the issue.