How to create a deep copy in Karate - karate

How can I create a totally independent copy of a variable in karate. So that changing one doesn't affect the other.
I tried simply assigning it to a new variable but it didn't work.
* def copyJson = originalJson
Changing copyJson changes the originalJson too.

This is possible, and explained in the documentation: https://github.com/intuit/karate#copy
* def original = { key: 'value' }
# this will create a "deep copy"
* copy foo = original

Related

Remove elements from a list in karate?

after using scripAll() to get list of style attribute values, I need to eliminate a few. Wanted to know if there is something like remove() in python which can be used for the same.
Example:
* def list_colors = ["rgb(245,60,86)", "rgb(245,60,86)", "rgb(245,00,00)", "rgb(245,00,00)" ]
Want to remove rgb(245,00,00) from the list. How can I do this in karate?
Thanks
I think you missed that scriptAll() can take a third "filter function" argument, please refer the docs: https://github.com/intuit/karate/tree/master/karate-core#scriptall-with-filter
* def list_colors = scriptAll('.my-css', "_.style['display']", x => !x.includes('245,00,00'))
Otherwise please refer JSON transforms: https://github.com/intuit/karate#json-transforms
* def filtered = karate.map(list_colors, x => !x.includes('245,00,00'))

How can I access value in sequence type?

There are the following attributes in client_output
weights_delta = attr.ib()
client_weight = attr.ib()
model_output = attr.ib()
client_loss = attr.ib()
After that, I made the client_output in the form of a sequence through
a = tff.federated_collect(client_output) and round_model_delta = tff.federated_map(selecting_fn,a)in here . and I declared
`
#tff.tf_computation() # append
def selecting_fn(a):
#TODO
return round_model_delta
in here. In the process of averaging on the server, I want to average the weights_delta by selecting some of the clients with a small loss value. So I try to access it via a.weights_delta but it doesn't work.
The tff.federated_collect returns a tff.SequenceType placed at tff.SERVER which you can manipulate the same way as for example client dataset is usually handled in a method decorated by tff.tf_computation.
Note that you have to use the tff.federated_collect operator in the scope of a tff.federated_computation. What you probably want to do[*] is pass it into a tff.tf_computation, using the tff.federated_map operator. Once inside the tff.tf_computation, you can think of it as a tf.data.Dataset object and everything in the tf.data module is available.
[*] I am guessing. More detailed explanation of what you would like to achieve would be helpful.

Using call read within a js function

I have a slight problem I want to solve. I have the following lines of code which create 2 users which works. However the issue is that, it creates both users with the same Id from the the first line of code:
def myId = call read('classpath:karate/helpers/guid.js')
def users = function(){ karate.call('classpath:v1/api_CreateUser.feature')}
def usersResult = karate.repeat(2, users )
So I want to be able to create multiple users with different Ids. I tried the following:
* def users =
"""
function(){
var myId = null;
if(myId == null)
{
myId = call read('classpath:karate/helpers/guid.js')
}
karate.call('classpath:v1/api_CreateUser.feature');
}
"""
def usersResult = karate.repeat(2, users )
So the idea is to reset the 'myId' variable everytime to null, check if null which will be true, then call the js function which generates the id and assign the result to 'myId' variable.
Then the variable will be used on the karate.call('classpath:v1/api_CreateUser.feature') line.
Unfortunately I'm getting javascript evaluation failed error.
Anyone could help?
Thanks
Be clear about the slight difference when you are in Karate and when you are in JS. For example:
myId = call read('classpath:karate/helpers/guid.js')
This won't work. What you are looking for is:
myId = karate.call('classpath:karate/helpers/guid.js');
I recommend you read and understand the section on Karate Expressions it will save you a lot of trouble later.
When you use a JS function (that works) you should never need to worry about what you are. Just invoke it wherever, and it will "dispense" a new value. For example if you have:
* def time = function(){ return java.lang.System.currentTimeMillis() + '' }
* def first = time()
* def second = time()
Here first and second will always be different. I think now you have all you need. You are trying to access a JS variable defined in Karate from within a function, this depends on when either was initialized and I don't recommend it if you don't know what you are doing. But if you want to access the latest value of a Karate variable, the right way is to use karate.get(varNameAsString).

karate xpath - Can we replace/delete a node

I'm looking to test error messages by modifying a valid xml message file.
I can easily add nodes like this in the scenario:
* def invalidDocumentId = read('Valid.xml')
* set invalidDocumentId /soapenv:Envelope/soapenv:Body = <tis:extraBonus>Extra</tis:extraBonus>
Given request invalidDocumentId
But I'd like to also remove nodes, update node names, change attribute names.
Is there a way to set that or do I need to call Java com.intuit.karate.XmlUtils.
First, removing and adding a node and even attributes should be easy, just use the remove and set keywords with XPath. They will over-write values if needed.
* def base = <query><name>foo</name></query>
* remove base /query/name
* match base == <query/>
* set base /query/foo = 'bar'
* set base /query/#baz = 'ban'
* match base == <query baz="ban"><foo>bar</foo></query>
And the good news is that if you have some really tricky XML manipulation requirements, the string replace syntax comes to the rescue. This is best explained in this other answer on Stack Overflow: https://stackoverflow.com/a/50367134/143475 | https://stackoverflow.com/a/53682733/143475

D3 Graph Example Using In Memory Object

This seems like it should be simple, but I have spent literally hours without any success.
Take the D3 graph example at http://bl.ocks.org/mbostock/950642. The example uses a local file called graph.json. I have set up a Rails app to serve a similar graph, however I don't want to write a file of the JSON. Rather, I generate the nodes and links into an object such as:
{"nodes":[{"node_type":"Person","name":"Damien","id":"damien_person"}, {"node_type":"Person","name":"Grant","id":"grant_person"}}],
"links":[{"source":"damien_person","target":"grant_person","label":"Friends"}}
Now when I render the D3, I need to update the call d3.json("graph.json", function(json) {...}); to reference my in-memory object rather than the local file (or url). However, everything I've tried breaks my html/javascript. For example I tried setting the var dataset = <%= raw(#myInMemoryObject) %>;, and that works for assignment (I did an alert on the dataset), however I can't get the D3 code to use it.
How can I replace the d3.json call in order to use my in-memory object?
Thank you,
Damien
Your idea of using, for example, var dataset = <%= raw(#myInMemoryObject) %>; is the right way to go but you need to prep your object to be in the right format.
The nodes specified in the links need to either be numeric references to nodes in the nodes array eg. 0 for first, 1 for second
var json ={
"nodes":[{"name":"Damien","id":"a"}, {"name":"Bob","id":"b"}],
"links":[{"source":0, "target":1,"value":1}]
}
or links to the actual objects which make the nodes themselves:
var a = {"name":"Damien","id":"a"};
var b = {"name":"Bob","id":"b"}
var json ={
"nodes":[a,b],
"links":[{"source":a,"target":b,"value":1}]
};
Relevant discussion is here: https://groups.google.com/forum/?fromgroups=#!topic/d3-js/LWuhBeEipz4
Example here: http://jsfiddle.net/5A9eV/1/