Printing SOAP response in Karate DSL - soap

I have this feature file and i get a response correctly. I want to print obtained value from response but somehow I am not able to do that. Tried to research some stuff but I couldnt help myself.
Can anyone help please? Thanks in advance
Feature:
test of soap
Background:
* url 'http://www.dataaccess.com/webservicesserver/numberconversion.wso'
Scenario: soap 1.1
Given request
"""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.dataaccess.com/webservicesserver/">
<soapenv:Header/>
<soapenv:Body>
<web:NumberToDollars>
<web:dNum>10</web:dNum>
</web:NumberToDollars>
</soapenv:Body>
</soapenv:Envelope>
"""
When soap action 'Conversion'
Then status 200
* print '\n', response
#working
* match response /Envelope/Body/NumberToDollarsResponse/NumberToDollarsResult == 'ten dollars'
#not working
* print response.Envelope.Body.NumberToDollarsResponse.NumberToDollarsResult
#not working
* print response /Envelope/Body/NumberToDollarsResponse/NumberToDollarsResult
#not working
* def x = response /Envelope/Body/NumberToDollarsResponse/NumberToDollarsResult
* print x

If you read the docs, print only handles JS on the right-hand-side, not XPath.
For what you want, please do in 2 steps:
* def temp = /Envelope/Body/NumberToDollarsResponse/NumberToDollarsResult
* print temp

Related

parsing soap response using Cypress

Facing issues while parsing this response using cypress,
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<p385:summaryOutputArray xmlns:p385="http://dataobject.simulation.com">
<p385:userName>MS</p385:userName>
</p385:summaryOutputArray>
</soapenv:Body>
</soapenv:Envelope>
Using Cypress How to read userName TAG? I can see in the log that whole xml is printed but can't get to the particular tag. Also, while using the function to get to the particular tag to get the value, I am getting null property
Firstly I used this. This is giving error. property reading null
const parser = new DOMParser();
const xmlDOM = parser.parseFromString(quoteResp, 'text/xml');
cy.log('xmlDOM ' + quoteResp.);
cy.wrap(Cypress.$(quoteResp)).then(quoteResp => {
const txt = quoteResp.filter('Body').find('p385:userName').text();
cy.log('value:' + txt);
});
Using this I can see the whole response in logs
then(quoteResp => {cy.log('xmlDOM ' + quoteResp.body);
It's not necessary to wrap the response, just query the xmlDOM like this
const xmlDOM = parser.parseFromString(quoteResp, 'application/xml');
const userName = xmlDOM.querySelector('userName').textContent
expect(userName).to.eq('MS')

Karate API - Getting 500 error while hitting SOAP service in batch

I am automating 3 APIs (Rest_1, Rest_2 and Soap_3 services) using Karate API. Basically Rest_1 output will be input to Rest_2 and Rest_2 output will be input to Soap_3. Created 3 feature files for each API and one master feature file that calls these 3 features. Rest_1-->Rest_2 flow is working as expected, Rest_2-->Soap_3 request XML is generating as expected but the same request is not hitting the Soap_3 service and getting the response 500.
When I execute Soap_3 feature file alone it is giving me the expected response. But in batch it is throwing 500 error.
If I take Rest_2-->Soap_3 generated XML and run it in SoapUI manually it is working fine.
Request your help in this issue. Thanks in advance !
Below is my Soap_3 service feature file:
Feature: Get PolicyDetails
Background:
* configure headers = {Content-Type: 'application/soap+xml; charset=utf-8'}
* configure logPrettyResponse = true
* configure ssl = true
* configure ssl = 'TLSv1.2'
* header Authorization = call read('classpath:resources/common/basic_auth.js') {username:'test',password:'test'}
* url 'https://soap_3apiurl'
Scenario: get the PolicyInfo
* configure charset = null
# getting submission id from preious feature file output
* call read('classpath:resources/dynamic/previous.feature'){'submissionID':'#(submissionID)'}
* xml req = read ('classpath:resources/common/RetrivePolicyDetails.xml')
* karate.set ('req/soapenv:Envelope/soapenv:Body/ns2:retrieveSubmission/ns2:aRequest/SubmissionID',submissionID)
Given request req
When soap action 'https://soap3apiurl'
Then status 200
And print response
**Console log:**
16:43:30.562 [ForkJoinPool-1-worker-1] DEBUG com.intuit.karate - response time in milliseconds: 58.18
1 < 500
1 < Accept-Encoding:
1 < Authorization: Basic
1 < Cneonction: close
1 < Content-Type: application/soap+xml; charset=UTF-8
1 < Cookie: NSC
1 < Date:
1 < Host: soap3APIurl.com
1 < Set-Cookie:
1 < Transfer-Encoding: chunked
1 < X-Forwarded-For: 10.00.00.1, 10.00.00.20
1 < X-Forwarded-Host:
1 < X-Forwarded-Server:
1 < X-dynaTrace: FW1;10000008;-1100030439;601946;6;-11000009;60194;1
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/">soap11Env:Server</faultcode>
<faultstring>Error while building message</faultstring>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
16:43:30.565 [ForkJoinPool-1-worker-1] ERROR com.intuit.karate - status code was: 500, expected: 200
Do not leave a space after the read function reference:
* xml req = read('classpath:resources/common/RetrivePolicyDetails.xml')
This is explained here: https://github.com/intuit/karate/tree/develop/karate-core#locator-lookup
If this is not the issue, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
* configure headers = {Cookie : null}
Adding above line resolved my issue. Thanks.

Mock response with repetitions in soapui

I'm trying to do mock response based on the request.
With a request like that:
<soapenv:Body>
<con:person>
<person>
<name>John</name>
<age>18</age>
</person>
</con:person>
</soapenv:Body>
and a reponse like that
<soapenv:Body>
<con:result>
<person>
<name>?</name>
<age>?</age>
<country>?</country>
<city>?</city>
</person>
</con:result>
</soapenv:Body>
I can use elements from the request to take what i want in database and create the response.
But when i have a request with many person like that
<soapenv:Body>
<con:person>
<person>
<name>John</name>
<age>18</age>
</person>
<person>
<name>Doe</name>
<age>50</age>
</person>
</con:person>
</soapenv:Body>
I don't know how i can take all data from the request and how i can use them to create a response like that:
<soapenv:Body>
<con:result>
<person>
<name>John</name>
<age>18</age>
<country>France</country>
<city>Paris</city>
</person>
<person>
<name>Doe</name>
<age>50</age>
<country>Spain</country>
<city>Madrid</city>
</person>
</con:result>
</soapenv:Body>
With the same number of person in the request and in the response.
I hope i was clear and i thank you for your answers.
I managed to do something similar. First, I defined my mock response object as:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stac="stackOverflow.question">
<soapenv:Header/>
<soapenv:Body>
<stac:result>
${personElements}
</stac:result>
</soapenv:Body>
</soapenv:Envelope>
I then created the content for ${personElements} using this Groovy script:
import groovy.xml.MarkupBuilder
// An array from which county and city will be drawn randomly
def countryArray = [["Australia", "Perth"],
["Spain", "Madrid"],
["England","London"],
["Brazil", "Rio"]]
def random = new Random()
// create XmlHolder for request content
def holder = new com.eviware.soapui.support.XmlHolder( mockRequest.requestContent )
// Get the name and age values from the request
def requestItems = holder.getNodeValues( "//*:person/*:person/descendant::*")
def writer = new StringWriter()
def personElements = new MarkupBuilder(writer)
// Build the response elements
for (int index = 0; index < requestItems.size() - 1; index += 2) {
personElements.'stac:person'() {
'stac:name'(requestItems[index])
'stac:age'(requestItems[index+1])
// Choose a random county and city from the array
def randomIndex = random.nextInt(countryArray.size())
'stac:country'(countryArray[randomIndex][0])
'stac:city'(countryArray[randomIndex][1])
}
}
// Add the newly created elements to the response
context.personElements = writer.toString()
This gave me a response like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stac="stackOverflow.question">
<soapenv:Header/>
<soapenv:Body>
<stac:result>
<stac:person>
<stac:name>Dolly Bonkers</stac:name>
<stac:age>42</stac:age>
<stac:country>Brazil</stac:country>
<stac:city>Rio</stac:city>
</stac:person>
<stac:person>
<stac:name>Mary Poppins</stac:name>
<stac:age>82</stac:age>
<stac:country>England</stac:country>
<stac:city>London</stac:city>
</stac:person>
<stac:person>
<stac:name>Bilbo Baggins</stac:name>
<stac:age>102</stac:age>
<stac:country>Australia</stac:country>
<stac:city>Perth</stac:city>
</stac:person>
<stac:person>
<stac:name>Johnny Hardcase</stac:name>
<stac:age>22</stac:age>
<stac:country>Spain</stac:country>
<stac:city>Madrid</stac:city>
</stac:person>
</stac:result>
</soapenv:Body>
</soapenv:Envelope>
The script just takes random city and country values from a small array but you could come up with something better if you wanted consistent responses for certain names.

Http client POST request xml+soap

I want to make a post request in Scala to this API http://api.atinternet-solutions.com/toolbox/reporting.asmx
I first did it with a curl like this :
curl -X POST -T post.txt -H "Content-Type: application/soap+xml; charset=utf-8" http://api.atinternet-solutions.com/toolbox/reporting.asmx -v
and I got what I expected.
Now I want to call the API programatically with a simple HttpClient
val httpClient = new DefaultHttpClient()
def postRequest=new HttpPost("https://api.atinternet-solutions.com/toolbox/reporting.asmx")
postRequest.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
postRequest.addHeader("SOAPAction","\"http://www.xiti.com/queryReport\"")
val file=new File("post.txt")
val fe=new FileEntity(file,"application/soap+xml;charset=utf-8")
postRequest.setEntity(fe)
val httpResponse=httpClient.execute(postRequest)
println(httpResponse.getStatusLine.toString)
val rspStr=Source.createBufferedSource(httpResponse.getEntity.getContent).mkString
println(rspStr)
but I get an HTTP/1.1 500 Internal Server Error
and printing the rspStr yields
"?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Receiver</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">Server was unable to process request. ---> Root element is missing.</soap:Text></soap:Reason><soap:Detail /></soap:Fault></soap:Body></soap:Envelope"
The post.txt looks like below, except I set the good information instead.
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<NXHeader xmlns="http://www.xiti.com/">
<GUID>string</GUID>
<SecurityKey>string</SecurityKey>
<Site>int</Site>
</NXHeader>
</soap12:Header>
<soap12:Body>
<queryReport xmlns="http://www.xiti.com/">
<startDate>int</startDate>
<endDate>int</endDate>
<query>string</query>
<param>string</param>
<typereport>XML or CSV</typereport>
</queryReport>
</soap12:Body>
</soap12:Envelope>
The curl action which is working is done from my scala project directory. I printed post.txt in scala and got the good content.
I cannot figure out what is going wrong. Thank you for your help
I tried your call with the dispatch library.
This is my code
import dispatch._
import java.io.File
object ToolBox {
val endpoint = url("https://api.atinternet-solutions.com/toolbox/reporting.asmx").POST
.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
.addHeader("SOAPAction",""" "http://www.xiti.com/queryReport" """)
def report = Http( endpoint <<< new File("post.txt") > as.xml.Elem)
def tryReport = {
val res = report.either
for {
ex <- res.left
} yield "Something got wrong " + ex.getMessage
}
}
The service replies with a status 500 like you, but the faultString in the response xml is: A parameter is missing in your NXHeader or you have a namespace issue.
Is it what you would expect, since the post.txt body contains only the placeholders from the query report example, instead of real parameters?
I found what was going wrong.
Replace
def postRequest
by
val postRequest.
Tks again

savon soap attributes

Am trying to query netsuite api for currencies. The following soap request works for me in SOAP UI client. But i am having a hard time trying to get the same working with ruby's savon gem version 0.9.7.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:urn1="urn:core_2012_2.platform.webservices.netsuite.com">
<soapenv:Header>
<urn:passport>
<urn1:email>xxx#abc.com</urn1:email>
<urn1:password>xxx</urn1:password>
<urn1:account>xxx</urn1:account>
</urn:passport>
</soapenv:Header>
<soapenv:Body>
<urn:getAll>
<urn:record recordType="currency"/>
</urn:getAll>
</soapenv:Body>
</soapenv:Envelope>
Basically i am not able to set the attribute on the urn:record element. The following is not working:
response = client.request :urn, :get_all do
soap.body = { "urn:record" => { :attributes! => { "recordType" => "currency" } } }
end
Please advise.
As explained on http://savonrb.com the key in the attributes! hash has to match the XML tag. You want to write something like this:
response = client.request :urn, :get_all do
soap.body = {'urn:record'=>'',
:attributes!=>{'urn:record'=>{'recordType'=>'currency'}}
}
end
Please let us know whether this solves it for you.
Double-check the raw soap request. :get_all may need to be "getAll" to have savon take you literally; it may be changing it to GetAll
In new versioin of savon you can place :attributes in the local context for the operation tag:
#interaction_client.call(:retrieve_interaction, message: message_hash, :attributes => { 'attachmentInfo' => include_attachments.to_s })
In this case, the attachmentInfo attribute will be placed into the main operation tag linked with operation, in this example this would be the ns:RetrieveInteractionRequest tag.
Please note that the syntax does not contains the exclamation mark.