How can I reuse a parameterized Postman test across endpoints? - postman

In Postman, I can create a set of common tests that run after every endpoint in the collection/folder Tests tab, like so:
pm.test("status code is 200", function () {
pm.response.to.have.status(200);
});
But how should I do this for my schema validation on the response object? Each endpoint has a different expected schema. So I have something like this on each individual endpoint:
const schema = { type: 'array', items: ... }
pm.test('response has correct schema', function () {
const {data} = pm.response.json();
pm.expect(tv4.validate(data, schema)).to.be.true;
});
I can't extract this up to the collection level because each schema is different.
Now I find that I want to tweak that test a little bit, but I'll have to copy-and-paste it into 50 endpoints.
What's the recommended pattern here for sharing a test across endpoints?

I had the same issue some years ago, and I found two ways to solve this:
Create a folder for each structure object
You can group all your test cases that share the same structure into a new folder and create a test case for this group. The issue with this is that you will be repeating the requests in other folders. (For this solution, you will need to put your "tests cases" into the folder level)
Create a validation using regular expressions (recommended)
Specify in the name of each request a set of rules (these rules will indicate what kind of structure or call they might have). Then you create a validation in the first parent folder for each type of variation (using regex). (You will need to create documentation and some if statements in your parent folder)
E.g.: [POST] CRLTHM Create a group of homes
Where each initial is meaning to:
CR: Response must be 201
LT: The response must be a list of items
HM: The type of the response must be a home object
And the regex conditional must be something like this (this is an example, please try to make your regex accurate):
if(/CRLTHM\s/.test(pm.info.requestName))
(In this image, NA is referring just to Not Authenticated)

Related

How to get regex value from $httpBackend whenGET

$httpBackend.whenGET(/api\/product\/[a-zA-Z0-9]{6}/).respond(function(data) {
// Code to find given ID in collection
});
When I call this endpoint, I should return the product that matches the given product ID (the regex value). How do I access this value? The data value just equals 'GET'.
I'm assuming you're using $httpBackend in a unit test. If that's so, you have two options. You can choose to use respond to define custom responses (which is what you are doing above).
Or you could use the passThrough method, which should actually call the API (which then makes your tests slightly more volatile as they are not self-reliant, a service interruption could cause the test to fail).
You can read about the .get (including whenGET) and .passThrough methods on the AngularJS $httpBackend documentation.
EDIT
$httpBackend.whenGET(/api\/product\/[a-zA-Z0-9]{6}/)
.respond(function(method, url, data, headers) {
/** do something with url */
});

Sitecore multisites website URL routing [duplicate]

This question already has answers here:
How to generate custom unique ID
(2 answers)
Closed 8 years ago.
I am working on sitecore multisites . I have multiple websites ex test1, test2, test3, test4. All are configured in webconfig. Means test1, test2 ,test3 and so on . So URL //test1 will always point to there local home folder which will be inside of test1/home.
But as per my requirement i have one global folder which are separate from all websites but pages inside of this will be common for all websites.
Ex:
sitecore/Root/Global/Category/A
sitecore/Root/test1
sitecore/Root/test2
sitecore/Root/test3
Now i am not able to get page A if i am in //test1 , and want to access page A and URL should be to //test1/Category/A.
Please help.
I'm not usually a fan of re-posting an exact answer that I posted previously, especially when I posted the original barely over a week ago, but the following is from this post.
Every page that is managed in Sitecore is a Sitecore Item. As such, you should be able to just navigate to the name of the player item. If you were trying to say in your post that category items are stored in globals and not as pages, then you are left with the following options:
Query String: test1/Category?categoryId={ID of Category}
If this is the route that you choose to take then I would suggest using the category item's Sitecore ID for the value of the query string parameter.
If you have other IDs then put the specified ID there, however it would be easiest with Sitecore IDs
What you would then do is get the item with the ID specified in the query string parameter (or get the item with the category ID specified in the query string parameter, depending on which route you take) and display the data for that category on the page
Sitecore.Context.Database.GetItem(Request.QueryString["categoryId"])
categoryItems.FirstOrDefault(categoryItem => categoryItem["Category ID"] == Request.QueryString["categoryId"])
Note that this assumes that the Category ID is a field, not the Sitecore ID
If it is the Sitecore ID then change the lambda to use categoryItem.ID == new ID(Request.QueryString["categoryId"]
Regardless of which one you use, I suggest adding null checks to the QueryString getter
Sublayout Parameters
If you use this method, the query string will not change and people will not be able to get to the page from the direct URL
The process is the same as for query strings, except that you are using Sublayout parameters instead
Note that you must set these in a parent sublayout or in Sitecore (which means that you have a separate page for each player - i.e. this would be a bad solution)
Virtual Items
This is really what I think you are looking for
This can be a lot of work if you do it from scratch, or you can use the Wildcard Module
If you do it from scratch, you will need a custom pipeline and/or processor for handling the requests
If the Wildcard Module isn't going to work, and if this is the case for all sites in your Sitecroe instance, you could write a custom item resolver and insert it in the httpBeginRequest pipeline right after the built in item resolver.
This is sort of from memory, but should get you started:
namespace Example
{
public class CategoryItemRewsolver : Sitecore.Pipelines.HttpRequest.HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
if (Sitecore.Context.Item != null) return; // Item has already been resolved
if (args.Context.Request.Path.StartsWith("Category"))
{
Sitecore.Context.Item = Sitecore.Context.Database.GetItem("sitecore/Root/Global" + args.Context.Request.Path);
}
}
}
}
You'll obviously want to replace paths with your own (And possibly allow them to be configured through the .config file).
Then patch this into the pipeline:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<httpRequestBegin>
<processor patch:after="*[#type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="Example.CategoryItemResolver,Example" />
</httpRequestBegin>
</pipelines>
</sitecore>
</configuration>

How to filter a Backbone collection on the server

Is there a common pattern for using Backbone with a service that filters a collection on the server? I haven't been able to find anything in Google and Stack Overflow searches, which is surprising, given the number of Backbone apps in production.
Suppose I'm building a new front end for Stack Overflow using Backbone.
On the search screen, I need to pass the following information to the server and get back a page worth of results.
filter criteria
sort criteria
results per page
page number
Backbone doesn't seem to have much interest in offloading filtering to the server. It expects the server to return the entire list of questions and perform filtering on the client side.
I'm guessing that in order to make this work I need to subclass Collection and override the fetch method so that rather than always GETting data from the same RESTful URL, it passes the above parameters.
I don't want to reinvent the wheel. Am I missing a feature in Backbone that would make this process simpler or more compatible with existing components? Is there already a well-established pattern to solve this problem?
If you just want to pass GET parameters on a request, you should just be able to specify them in the fetch call itself.
collection.fetch( {
data: {
sortDir: "ASC",
totalResults: 100
}
} );
The options passed into fetch should directly translate to a jQuery.ajax call, and a data property should automatically get parsed. Of course overriding the fetch method is fine too, especially if you want to standardize portions of the logic.
You're right, creating your own Collection is the way to go, as there are not standards about server pagination except OData.
Instead of overriding 'fetch', what I usually do in these cases is create a collection.url property as a function, an return the proper URL based on the collection state.
In order to do pagination, however, the server must return to you the total number of items so you can calculate how many pages based on X items per page. Nowadays some APIs are using things like HAL or HATEOAS, which are basically HTTP response headers. To get that information, I normally add a listener to the sync event, which is raised after any AJAX operation. If you need to notify external components (normally the view) of the number of available items/pages, use an event.
Simple example: your server returns X-ItemTotalCount in the response headers, and expects parameters page and items in the request querystring.
var PagedCollection = Backbone.Collection.extend({
initialize: function(models,options){
this.listenTo(this, "sync", this._parseHeaders);
this.currentPage = 0;
this.pageSize = 10;
this.itemCount = 0;
},
url: function() {
return this.baseUrl + "?page=" + this.currentPage + "&items=" + this.pageSize;
},
_parseHeaders: function(collection,response){
var totalItems = response.xhr.getResponseHeader("X-ItemTotalCount");
if(totalItems){
this.itemCount = parseInt(totalItems);
//trigger an event with arguments (collection, totalItems)
this.trigger("pages:itemcount", this, this.itemCount);
}
}
});
var PostCollection = PagedCollection.extend({
baseUrl: "/posts"
});
Notice we use another own property, baseUrl to simplify extending the PagedCollection. If you need to add your own initialize, call the parent's prototype one like this, or you won't parse the headers:
PagedCollection.protoype.initialize.apply(this,arguments)
You can even add fetchNext and fetchPrevious methods to the collection, where you simply modify this.currentPage and fetch. Remember to add {reset:true} as fetch options if you want to replace one page with the other instead of appending.
Now if your backend for the project is consistent, any resource that allows pagination on the server may be represented using one PagedCollection-based collection on the client, given the same parameters/responses are used.

Emberjs New routing and query string or custom route matcher

I'm trying to migrate my app to the new emberjs routing API.
With old router I had some workarounds to provide similar URI for objects saved by ID and for new objects which described by set of params. This were done for ability of exchange links to objects between users without permanently saving it. This is two simplified valid routes from my app:
/objects/12 // fetch object by id (/objects/:object_id)
/objects/<serialized params> // build new object from params (/objects/:params)
Both of this routes are similar to router because they all have dynamic parts and static parts are equal. So I wrote custom RouteMatcher to pickup right route. Lack of query string parsing forced me to do this hack as quick and semilegal solution, also there is ancient ticket about this feature on github.
With the new router matching has been extracted to separate package (route-recognizer) so I cannot do the trick (or it will be full of hacks and injections).
As I can see I have to choose from these options:
Totally rewrite my URIs and separate all intersecting routes
Rewrite URIs but try to implement query string parser for the new Ember.Router
Put all logic into one route and reimplement only serialize/deserialize methods (something dirty)
Second solution seems to be more clean.
What will be the best non complicated decision? Should I try to find another way?
The current router does not support query-string parameters.
We are tracking this bug at https://github.com/emberjs/ember.js/issues/1773. You may want to follow it.
In the meantime, your best bet is probably to use a dynamic segment and manually serialize (with the serialize hook) and deserialize (with the model hook).

Load testing with SOAP UI

I have a SOAP UI 4.5.1, I have made a load test, it is working fine. My problem is that I run the same request every time and I need to change the values of the soap request I am sending.
For e.g. I have a block of my soap request:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SHL</ns:ProviderId>
<ns:ProjectId>SampleAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
Provider ID: SHL
Project ID: SampleAssessment
Is there a way to make those values changing from some kind of interval?
For e.g.: Provider IDs [SHL, SLH, LHS]
Project IDs [SampleAssessment, TestAssessment, AnotherAssessment]
And with a load test I am making three request so that for the first request values looks like this:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SHL</ns:ProviderId>
<ns:ProjectId>SampleAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
for the second like this:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SLH</ns:ProviderId>
<ns:ProjectId>TestAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
and so on...
Is there a way to make this happen with SOAP UI?
From my experience, you will need to use a Groovy Script step.
For example, if you have a step before your request that is a script, you can use something like:
context.setProperty("ProviderId", "SHL")
Then in your request, use:
<ns:ProviderId>${ProviderId}</ns:ProviderId>
Of course, this doesn't buy you much by itself. There are few ways to vary what the context.setProperty("ProviderId", "SHL") line will set. You can create a collection and iterate over it using something like:
def providers = ['ABC', 'DEF', 'GHI', 'JKL']
providers.each() {
context.setProperty("ProviderId", it)
testRunner.runTestStepByName( "nameofteststep" )
}
Where "nameofteststep" is the name of the Soap Request test step. This might sound odd, but if you right click the test step and disable it, the groovy script will still be able to execute it but it will not run sequentially. By that I mean that the groovy script will run it 4 times, but it won't run a fifth time when the script is complete because it is after the script. Then you just need to keep in mind that each load test thread makes four requests, but I am pretty sure that the SoapUI statistics will take this into account for you... might want to keep an eye out for it, though.
Alternatively, you could check the 'threadIndex' and set a the context variable based on that. A bit like this here: Log ThreadCount.
You could also use a collection without a loop and increment an index that you save as a testcase property and send the string corresponding to the index.
Personally, I think the first way is the most straightforward but I can provide an example of the other ones if you like.
There is a simple way of doing this without writing a groovy script.
After creating a test case you should include the below test steps:
1-Data source
2-Request
3-Loop
Data source will read an excel file (or other data source methods such as XML, groovy, JDBC, gird .. however the excel is the simplest one).
You should include the datas (that you need to change within the request)
Within the test request you need the right click and select "get data" . please notice that your test request should be as below
<ns:ProviderId>${ProviderId}</ns:ProviderId>
Then the last step is the "Loop" . This for returning to the first step until the data ends.
I hope this helps.