I am new(trainee) to the web development and I just started studying its "language". I have to report every day to my boss but I have to use the correct terms. I have been reading about URL anatomy, in order to explain the fragments of this URL: https://www.c2ccertified.org/api_v2/search&username=rikotech&offset=50.
I see something that looks like query parameters to me: offset and username, but I don't see the question mark.
I don't know how to fragment(in correct terms) this part of the URL:
search&username=rikotech&offset=50
Are these query parameters? Because it seems to me that they serve that purpose - semantically. They filter the result from the API server.
------EDIT------
I found useful tool to use Node.js URL parser:
url = new URL(`https://www.c2ccertified.org/api_v2/search&username=rikotech&offset=50`)
console.log(url);
It did the job for me:
URL {
href:
'https://www.c2ccertified.org/api_v2/search&username=rikotech&offset=50',
origin: 'https://www.c2ccertified.org',
protocol: 'https:',
username: '',
password: '',
host: 'www.c2ccertified.org',
hostname: 'www.c2ccertified.org',
port: '',
pathname: '/api_v2/search&username=rikotech&offset=50',
search: '',
searchParams: URLSearchParams {},
hash: '' }
If there's no "?", then there's no query, thus no query arguments. See https://www.greenbytes.de/tech/webdav/rfc3986.html#components.
Related
Files for the scenario
All the files are on same directory.
title-update-request.json
{id: 12, name: 'Old Hello', config:[{username: 'qwe', password: 'tyu'},{username: 'abc', password: 'xyz'}]}
title-update-response.json
{id: 12, name: 'New Hello', config:[{username: 'qwe', password: 'tyu'},{username: 'abc', password: 'xyz'}]}
title-update-error-request.json
{id: 00, name: 'Old Hello', config:[{username: 'qwe', password: 'tyu'},{username: 'abc', password: 'xyz'}]}
title-update-error-response.json
{Error: 'not found', Message: 'The provided Book is not found.'}
book-record.feature
Feature: CRUD operation on the book records.
Background:
* def signIn = call read('classpath:login.feature')
* def accessToken = signIn.accessToken
* url baseUrl
Scenario: Change title of book in the single book-record.
* json ExpResObject = read('classpath:/book-records/title-update-response.json')
* json ReqObject = read('classpath:/book-records/title-update-request.json')
* call read('classpath:/book-records/update.feature') { Token: #(accessToken), ReqObj: #(ReqObject), ResObj: #(ExpResObject), StatusCode: 200 }
Scenario: Change title of book in the non-existing book-record.
* json ExpResObject = read('classpath:/book-records/title-update-error-request.json')
* json ReqObject = read('classpath:/book-records/title-update-error-response.json')
* call read('classpath:/book-records/update.feature') { Token: #(accessToken), ReqObj: #(ReqObject), ResObj: #(ExpResObject), StatusCode: 400 }
update.feature
Feature: Update the book record.
Scenario: Update single book-record.
Given path '/book-record'
And header Authorization = 'Bearer ' + __arg.Token
And header Content-Type = 'application/json'
And request __arg.ReqObj
When method put
Then status __arg.StatusCode
And response == __arg.ExpectedResponse
Actual API response for scenario: 1 is :
{name: 'New Hello', config:[{username: 'abc', password: 'xyz'},{username: 'qwe', password: 'tyu'}]}
Actual API response for scenario: 2 is :
{Error: 'not found', Message: 'The provided Book is not found.'}
Question: How should I validate the response in update.feature file since problem is if I make change s as using #^^config that will not works for scenario :2 and response == _arg.ExpectedResponse is not working for Scenario: 1?
This is classic over-engineering of tests. If someone has told you that "re-use" is needed for tests, please don't listen to that person.
You have two scenarios, one happy path and one negative path. I am providing how you should write the negative path here below, the rest is up to you.
Scenario: Change title of book in the non-existing book-record.
Given path 'book-record'
And header Authorization = 'Bearer ' + accessToken
And request {id: 00, name: 'Old Hello', config:[{username: 'qwe', password: 'tyu'},{username: 'abc', password: 'xyz'}]}
When method put
Then status 400
And response == {Error: 'not found', Message: 'The provided Book is not found.'}
See how clean it is ? There is no need for "extreme" re-use in tests. If you still insist that you want a super-generic re-usable feature file that will handle ALL your edge cases, you are just causing trouble for yourself. See how un-readable your existing tests have become !!
EDIT: Since I refer the question to others often as an example of how NOT to write tests, I wanted to make my point more clear and add a couple of links for reference.
Sometimes it is okay to "repeat yourself" in tests. Tests don't have to be DRY. Karate is a DSL that enables you to make HTTP calls or JSON manipulation in one or two lines. When you start attempting "re-use" like this, it actually leads to more harm than good. For example, you now need to look at multiple files to understand what your test is doing.
If you don't believe me, maybe you will believe the team at Google: https://testing.googleblog.com/2019/12/testing-on-toilet-tests-too-dry-make.html
I have a very simple request to make but it looks like HttpPoison isn't able to resolve this.
The request has attachments, so i'm using multipart/form-data content type.
When I send just the file, the request works fine, but I need to add some other props to my request and that's where the issue comes.
My request:
HTTPoison.post(
"path.com/api/anything",
{:multipart, [
{
:file,
"/path/file.xlsx",
{"form-data", [name: "file", filename: "file.xlsx"]}, []
},
{"taskName", "#{task.name}"},
{"taskLink", "#{task.link}"}
]},
)
I receive the file without problems but the taskName and taskLink never reach the server.
( I tried with postman and had no problems )
Some issues related to this:
https://elixirforum.com/t/httpoison-post-multipart-with-more-form-than-the-file/4222/4
https://github.com/edgurgel/httpoison/issues/237
We have a working example of the multipart list that we use to send zip files along with other attributes. Something equivalent to this might work for you.
[
{"id", to_string(order_id)},
{"file_size", to_string(file_size)},
{"attachment", file, {"form-data", [name: "file", filename: filename]},
[{"Content-Type", "application/zip"}]
}
]
In order to validate the installation of WordPress instances, we are writing Python unit tests. One of the test should perform the following action: upload an image to WordPress.
In order to do that, I am using the Requests library.
When I inspect the form within /wp-admin/media-new.php page through Firebug (form information, I get the following information):
Form
Id: file-form
Name
Method: post
Action: http://localhost:8000/wp-admin/media-new.php
Elements
id: plupload-browse-button
type: button
value: Select Files
id:async-upload
name: async-upload
type: file
label: Upload
id:html-upload
name: html-upload
type: submit
value: Upload
id: post_id
name: post_id
type: hidden
value: 0
id: _wpnonce
name: _wpnonce
type: hidden
value: c0fc3b80bb
id: file-form
name: _wp_http_referer
type: hidden
value: /wp-admin/media-new.php
I believe that the _wpnonce is a unique value generated for each session. Therefore, before trying to upload the file, I get the media-new.php page and grab the _wpnonce in the form (hence the variable in my code).
My code is the following:
with open('1.jpg', 'rb') as f:
upload_data = {'post_id': '0',
'_wp_http_referer': '/wp-admin/media-new.php',
'_wpnonce': wp_nonce,
'action': 'upload_attachement',
'name': '1.jpg',
'async-upload': f,
'html-upload': 'Upload'}
upload_result = session.post('http://localhost:8000/wp-admin/media-new.php', upload_data)
The code runs fine and the upload_result.status_code equals 200.
However, the image never shows up in the media gallery of WordPress.
I believe this a simple error, but I can't figure out what I'm missing.
Thanks in advance for the help.
If you want to post files you should use the files parameter. Also the '_wpnonce' value is not enough to get authenticated, you need to have cookies.
url = 'http://localhost:8000/wp-admin/media-new.php'
data = {
'post_id': '0',
'_wp_http_referer': '/wp-admin/media-new.php',
'_wpnonce': wp_nonce,
'action': 'upload_attachement',
'html-upload': 'Upload'
}
files = {'async-upload':('1.jpg', open('1.jpg', 'rb'))}
headers = {'Cookie': my_cookies}
upload_result = session.post(url, data=data, files=files, headers=headers)
I'm assuming that you have acquired valid cookies from your browser. If you want to get authenticated with requests check my answer to this post: login-wordpress-with-requests
I'm developing an app with Spring MVC and the view in extjs 4. At this point, i have to create a Grid which shows a list of users.
In my Spring MVC controller i have a Get method which returns the list of users in a jsonformat with "items" as a root.
#RequestMapping(method=RequestMethod.GET, value="/getUsers")
public #ResponseBody Users getUsersInJSON(){
Users users = new Users();
users.setItems(userService.getUsers());
return users;
}
If i try to access it with the browser i can see the jsondata correctly.
{"items":[{"username":"name1",".....
But my problem is relative to request of the Ext.data.Store
My Script is the following:
Ext.onReady(function(){
Ext.define('UsersList', {
extend: 'Ext.data.Model',
fields: [
{name:'username', type:'string'},
{name:'firstname', type:'string'}
]
});
var store = Ext.create('Ext.data.Store', {
storeId: 'users',
model: 'UsersList',
autoLoad: 'true',
proxy: {
type: 'ajax',
url : 'http://localhost:8080/MyApp/getUsers.html',
reader: {type: 'json', root: 'items'}
}
});
Ext.create('Ext.grid.Panel',{
store :store,
id : 'user',
title: 'Users',
columns : [
{header : 'Username', dataIndex : 'username'},
{header : 'Firstname', dataIndex: 'firstname'}
],
height :300,
width: 400,
renderTo:'center'
});
});
When the store tries to retrieve the data and launchs the http request, in my firebug console appears OPTIONS getUsers.html while the request in the browser launchs GET getUsers.html
As a result, Ext.data.Store has not elements and the grid appears with the columnames but without data. Maybe i've missed something
Thank you
You can change the HTTP methods that are used by the proxy for the different CRUD operations using actionMethods.
But, as you can see in the doc (and as should obviously be the case), GET is the default for read operations. So the OPTIONS request you are observing is quite puzzling. Are you sure that there's not another part of your code that overrides the default application-wide? Maybe do a search for 'OPTIONS' in all your project's JS files, to try and find a possible suspect. Apparently there's no match in the whole Ext code, so that probably doesn't come from the framework.
Edit:
Ok, I think I've got it. If your page is not accessed from the same domain (i.e. localhost:8080, the port is taken into account), the XHR object seems to resort to an OPTIONS request.
So, to fix your problem, either omit the domain name completely, using:
url: '/MyApp/getUsers.html'
Or double check that your using the same domain and port to access the page and make the requests.
Whenever I call the below method (CoffeeScript) that is on the server I get "Scripts should use an informative User-Agent string with contact information, or they may be IP-blocked without notice" from Wikipedia. How do I include user-agent info in the call? Or does it grab this from Meteor Accounts (which I'm not using yet)? thank you for any help...
Meteor.methods
wpSearch: (queryStr) ->
result = Meteor.http.call "GET", "http://en.wikipedia.org/w/api.php",
params:
action: "query"
list: "search"
format: "json"
srwhat: "text"
srsearch: queryStr
To clarify the previous answer for future visitors, the syntax for Meteor.http.get is as follows:
result = Meteor.http.get("https://api.github.com/user", {
headers: {
"User-Agent": "Meteor/1.0"
},
params: {
access_token: accessToken
}
});
Note the curly braces around the headers option and the comma afterwards separating the headers and params options (it's a syntax error without these things). This is example is part of the EventedMind how-to to customize the loginButtons during the onCreateUser() callback.
Just set User-Agent in the headers parameter (see http://docs.meteor.com/#meteor_http)
Meteor.methods
wpSearch: (queryStr) ->
result = Meteor.http.call "GET", "http://en.wikipedia.org/w/api.php",
headers:
"User-Agent": "Meteor/1.0"
params:
action: "query"
list: "search"
format: "json"
srwhat: "text"
srsearch: queryStr