Does Karate support the COPY HTTP Method or allow for custom HTTP methods? - karate

I have tried setting method to "copy", "mkcol", "lock", "unlock", etc and I have yet to find one that does not cause a Karate ERROR:
org.graalvm.polyglot.PolyglotException: ReferenceError: "copy" is not defined
Is there a way to use HTTP Methods like COPY, or do we need to request the feature?
Thank you!

Karate supports variable references after the method keyword. So this works, try it:
* def copy = 'copy'
* url 'https://httpbin.org/anything'
* method copy
Actual output: (although this server does not support COPY)
1 > COPY https://httpbin.org/anything
1 > Host: httpbin.org
1 > Connection: Keep-Alive
1 > User-Agent: Apache-HttpClient/4.5.13 (Java/17.0.5)
1 > Accept-Encoding: gzip,deflate
Refer: https://github.com/karatelabs/karate#method

Related

How to execute a global feature file first every time when Karate suite is executed and store the outcome in variables to be used further? [duplicate]

So I've managed to write a bunch of tests and in every feature file I set the same request headers.
For example:
Given url appUrl
And path '/path'
* header Accept = 'application/json'
I'd like to know if there's a way to set a header once so that it is set before each scenario is run. I've read the documentation and tried the callSingle method as follows in karate-config.js:
karate.callSingle('classpath:api/Utilities/Feature/header.feature');
header.feature looks like:
Feature: common routing that sets the headers for all features
Background:
* configure headers = { Accept : 'application/json' }
And example feature where I expect the headers to be preset:
Feature: Header Preset
Scenario: I expect the header to be set
Given url appUrl
And path '/path'
When method get
Then status 200
* print response
#I expect the response to be returned in JSON format
However I'm unable to get this working. I don't think I've understood how the callSingle method works. Some pointers would be helpful. Thanks.
Ignore callSingle for now and focus on configure headers.
I think you are missing one step - which is to ensure that configure headers has been "applied" before each Scenario. If you are 100% sure that this applies "globally", just do this in karate-config.js:
karate.configure('headers', { Accept: 'application/json' });
Else you use the Background (in each feature):
* configure headers = { Accept: 'application/json' }
Typically you have more steps that are common, so you have them in a "common" feature file and call that for every test. Refer: https://github.com/intuit/karate#shared-scope

How to run a setup feature only once before all other test case features correctly? [duplicate]

So I've managed to write a bunch of tests and in every feature file I set the same request headers.
For example:
Given url appUrl
And path '/path'
* header Accept = 'application/json'
I'd like to know if there's a way to set a header once so that it is set before each scenario is run. I've read the documentation and tried the callSingle method as follows in karate-config.js:
karate.callSingle('classpath:api/Utilities/Feature/header.feature');
header.feature looks like:
Feature: common routing that sets the headers for all features
Background:
* configure headers = { Accept : 'application/json' }
And example feature where I expect the headers to be preset:
Feature: Header Preset
Scenario: I expect the header to be set
Given url appUrl
And path '/path'
When method get
Then status 200
* print response
#I expect the response to be returned in JSON format
However I'm unable to get this working. I don't think I've understood how the callSingle method works. Some pointers would be helpful. Thanks.
Ignore callSingle for now and focus on configure headers.
I think you are missing one step - which is to ensure that configure headers has been "applied" before each Scenario. If you are 100% sure that this applies "globally", just do this in karate-config.js:
karate.configure('headers', { Accept: 'application/json' });
Else you use the Background (in each feature):
* configure headers = { Accept: 'application/json' }
Typically you have more steps that are common, so you have them in a "common" feature file and call that for every test. Refer: https://github.com/intuit/karate#shared-scope

Telegram Bot API: getChatMember throws USER_ID_INVALID for valid user

I'm trying to find out if a specific User is present in a supergroup, in order to keep track of those who left.
For that, I'm calling the Bot API method getChatMember for each User and checking if their status is either Left or Kicked. However, I noticed that (recently?) I'm getting USER_ID_INVALID errors for many valid users that are either in the supergroup or have been in the past and then left. I also confirmed that those accounts are still active on Telegram.
Here's the HTTP request I'm sending:
POST https://api.telegram.org/botXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXX/getChatMember HTTP/1.1
Connection: Keep-Alive
Content-Type: application/json; charset=utf-8
Content-Length: 46
Host: api.telegram.org
{"chat_id":-0000000000000,"user_id":000000000}
And here's the response I'm getting:
HTTP/1.1 400 Bad Request
Server: nginx/1.12.2
Date: Fri, 20 Apr 2018 04:17:32 GMT
Content-Type: application/json
Content-Length: 74
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Length,Content-Type,Date,Server,Connection
{"ok":false,"error_code":400,"description":"Bad Request: USER_ID_INVALID"}
Any way I look at it, it looks like a perfectly valid request to me. And I haven't been able to find a common pattern between the users that throw this error.
What am I missing here?
EDIT: As #sean pointed out, having one of those users message the bot privately fixed the error for that particular user. But I'm absolutely sure that user was seen before because that's how I got his user ID. What could have caused the bot "forget" about him and how would I prevent this from happening in the future?
This error means your bot haven't seen this user before.
For instance, my user ID is 109780439, you can try getChatMember with #PublicTestGroup, it should response with 400 error.
And then, forward ANY of my message (e.g., this) to your bot, you will see the different result :)
You will create a variable who get your channel's result, like this:
$join : api.telegram.org/botYOURTOKEN/getchat .....
if($message && (strpos($join,'"status":"left"') or strpos($join,'"Bad Request: USER_ID_INVALID"') or strpos($join,'"status":"kicked"'))!== false) {
}

Unable to configure Content-Type header from karate

am trying to configure the header 'Content-Type' from karate and I am not able to do so. I tried these * configure headers = {'Content-Type' : 'application/json;charset=UTF-8'} and * header Content-Type = 'application/json;charset=UTF-8'. But in the post call I am making , I always get Content-Type: text/plain which is wrong. Can anyone help? Thanks a lot!
Actually, never mind. I got over this by just adding * header Content-Type = 'application/json' rather than Content-Type' : 'application/json**;charset=UTF-8. I removed ;charset=UTF-8. If i add this, it breaks. I get an error java.lang.IllegalArgumentException: MIME type may not contain reserved characters
at org.apache.http.util.Args.check(Args.java:36).

WCF OData patching an entity set

Is it possible in update multiple entites based on a filter query in a batch request?
As an example of what I'm trying to achieve, say I want to update all product categories from foo to bar in one request to an OData endpoint, is there something like this that would work:
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed; boundary=changeset_fa7b-4aa9-a01f
GET /api/products?$filter=category eq 'foo' HTTP/1.1
Accept:application/json
Content-ID: 1
--changeset_fa7b-4aa9-a01f
Content-Type: application/http
Content-Transfer-Encoding: binary
PATCH $1 HTTP/1.1
Accept: application/json
Content-Type: application/json;odata=verbose
{"category":"bar"}
--changeset_fa7b-4aa9-a01f--
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--
I'm afraid the answer is no. There's no support for that in the protocol. And even if you remove the filtering from the question, trying to update all entities in the entity set so that they will have a same new value, the answer is still no.
You could probably do this yourself. Like,
Get /service.svc/MyEntitySet
and for every entity you get back, send a PATCH to update it individually.
In addition, if this kind of operation is going to be done frequently, the service author could write a specific service operation or action to do this on the server side. For example, write something called "ClearAllNames", and a user could invoke that, and the server would go through every entity and clear its name field.