I am earning unit testing. I know that best practice is that the functions should have local scope and they return something for example
export function test(arr) {
let arr2 = [];
for(let i = 0;i < arr.length;i++) {
if(arr[i] % 2 === 0) {
arr2.push(arr[i])
}
}
return arr2;
}
i can write the test for this function very simple - where i will expect some result
import { it, expect } from 'vitest';
it('should return even numbers', () => {
let result = test([1,2,3,4]);
expect(result).toEqual([2,4])
})
but I wonder, in functions where the global scope is modified from some function and the function is not returning anything for example
let arr2 = [];
export function test(arr) {
for(let i = 0;i < arr.length;i++) {
if(arr[i] % 2 === 0) {
arr2.push(arr[i])
}
}
}
how can i write test for such a functions ? How can i assume that arr2 will containt [2,4] at the end ?
Related
I dont know how to get the variable allP out of this function so i can return it to display on screen.
Ive tried defining the variable outside the function so i could call it in the code but that didnt work. the array prints out in the console log but i just cant seem to get it to show in the return.
sched = async () => {
var i = null;
var getPrice = null;
var allP =[];
try {
const schedinfo = await API.graphql(graphqlOperation(netidget));
this.setState({ schedinfo: schedinfo.data.listLoginModals.items });
for (i = 0; i < schedinfo.data.listLoginModals.items.length; i++) {
getPrice = schedinfo.data.listLoginModals.items[i].Type;
var lowP = await API.graphql(
graphqlOperation(lowest, {
CIndex: getPrice
})
)
if(typeof lowP.data.listlowestprice.items[0] == "undefined") {
lowP = "-";
} else {
lowP = lowP.data.listlowestprice.items[0].Price.toString();
}
if(lowP == " ") {
lowP = "-";
}
allP.push(lowP);
}
console.log(allP);
{this.state.lowprices.map(da => (
<View item={da} key={da.id}>
<Text>{da.Price}</Text>
console.log(da.Price)
</View>
))}
console.log(schedinfo.data.listLoginModals.items.length)
} catch (err) {
console.log('error creating restaurant...', err);
}
};
I want to be able to display the allP array that gets created from the function. Please any help is appreciated thank you so much
Move your code inside of your try sentence to a new async fuction, return it and receive that value on your allP variable (without arrow functions), so:
constructor(){
super();
this.getAllP = this.getAllP.bind(this);
this.sched = this.sched.bind(this);
}
async getAllP() {
try {
....
operations
....
return allP
}
}
async sched() {
var allP = await getAllP();
}
In Newman I want to test to ensure that the response code is correct, response time is reasonable and response values are correct.
In some cases, due to network hiccups or other system conditions, some requests might end up with timeouts or incorrect values that will resolve if the same request was processed a few seconds later.
in such cases, I would like to retry the exact request x times with a Y timeout between requests.
If an iteration pass after a retry, I would like the Newman exit code to be 0 (successful run).
After few hours I had ended up with a function like this:
function retryOnFailure(successCode, numberOfRetrys) {
var key = request.name + '_counter';
var execCounter = postman.getEnvironmentVariable(key) || 1;
var sleepDuration = 1000;
var waitUntilTime = new Date().getTime() + sleepDuration;
if (responseCode.code !== successCode && execCounter <= numberOfRetrys) {
while (new Date().getTime() < waitUntilTime) {
// Do Nothing -> Wait
}
console.log('Retrying: ' + request.name + '\nGot: ' + responseCode.code + ' Expected: ' + successCode + '\nWaited: ' + sleepDuration / 1000 + 'sec \nRetry Number: ' + execCounter + ' of ' + numberOfRetrys);
execCounter++;
postman.setEnvironmentVariable(key, execCounter);
postman.setNextRequest(request.name);
}
}
Usage:
retryOnFailure(404, 4);
You can setup a request workflow like this:
Create a collection with a request, then:
In the pre-request tab you can implement a counter:
// Counter for number of requests
var counter = environment.counter ? _.parseInt(environment.counter) + 1 : 1;
postman.setEnvironmentVariable("counter", counter);
Your tests tab would look like this:
const code = (responseCode.code === 200);
if (code === 200 && environment.counter < X) {
// Stop execution
tests["Status code is 200"] = code;
postman.setNextRequest();
}
else {
// retry the same request
postman.setNextRequest("Name of this request");
}
A timeout for the request itself can be configured with the newman CLI:
newman run myCollection.json --timeout-request Y
Here is the reusable function for the same
postmanFunctions.common.retryOnFailure(predicate,retryCount,waitbetweenRetrySec,ReroutetorequestifNeeded ,postmanAssertions);
predicate function decides success or failure
assertion function has all postman assertion
if reroute is blank then after retry attempts assertions gets executed.
Flexible polling with retrycount and waittime(if predicate passed no more
polling/reflow)
There is a maxflow counter(env var) which limits the number of flow jumps to
avoid infinite loop
Store the below function in Globals or env:
() => {
var sleep = (sleepDuration) => {
var startTime = new Date().getTime();
while (new Date().getTime() - startTime < sleepDuration) {}
}
var sleepByAsyncDelayTime = () => {
var sleepDuration = postman.getEnvironmentVariable('asyncDelayTime') || 0;
sleep(sleepDuration);
}
var retryOnFailure = (predicate, numberOfRetrys, sleepDuration, reRouteRequestName, postmanAssertions) => {
var retryCountPerReq_key = request.name + '_retry_count';
var retryCountPerReq = pm.environment.get(retryCountPerReq_key) || 0;
var reflowCountPerReq_key = request.name + '_reflow_count';
var reflowCountPerReq = pm.environment.get(reflowCountPerReq_key) || 0;
var totalReflowCount_key = 'totalReflowCount';
var totalReflowCount = pm.environment.get(totalReflowCount_key) || 0;
var maxReflowCounter = postman.getEnvironmentVariable('maxReflowCounter') || 0;
var maxReflowCounterPerReq = postman.getEnvironmentVariable('maxReflowCounterPerReq') || 0;
function clearAndExit() {
pm.environment.unset(retryCountPerReq_key);
pm.environment.unset(reflowCountPerReq_key);
postmanAssertions();
}
function retry() {
sleep(sleepDuration);
pm.environment.set(retryCountPerReq_key, ++retryCountPerReq);
postman.setNextRequest(request.name);
}
function reFlow() {
if (totalReflowCount < maxReflowCounter && reflowCountPerReq < maxReflowCounterPerReq) {
pm.environment.unset(retryCountPerReq_key);
pm.environment.set(totalReflowCount_key, ++totalReflowCount);
pm.environment.set(reflowCountPerReq_key, ++reflowCountPerReq);
postman.setNextRequest(reRouteRequestName);
} else clearAndExit();
}
if (predicate()) clearAndExit();
else if (retryCountPerReq < numberOfRetrys) retry();
else if (reRouteRequestName != '') reFlow();
else clearAndExit();
}
return {
common: {
sleepByAsyncDelayTime,
sleep,
retryOnFailure
}
};
}
Here is my retry function that I define in collection pre-request script. It only works when tests are executed via collection :
Utils = {
wait: function (that, sleepDuration){
that.setTimeout(() => {}, sleepDuration);
},
withRetry: function(that, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, businessRetryConditionCallBack, endRetryCallback){
if (!that.pm.environment.get("collection_tries")) {
that.pm.environment.set("collection_tries", 1);
}
if (((that.pm.response.code != expectedHttpStatus) || businessRetryConditionCallBack())
&& (that.pm.environment.get("collection_tries") <= maxNumberOfTries)) {
var tries = parseInt(that.pm.environment.get("collection_tries"), 10);
that.pm.environment.set("collection_tries", tries + 1);
Utils.wait(that, sleepBetweenTries, maxNumberOfTries);
that.postman.setNextRequest(that.request.name);
} else {
if(businessRetryConditionCallBack()){
// On ne passe pas à la requête suivante
that.postman.setNextRequest(null);
}
that.pm.environment.unset("collection_tries");
endRetryCallback();
}
}
};
And here is how to use it in request on pre-request or test scripts :
var expectedHttpStatus = 200;
var maxNumberOfTries = 5;
var sleepBetweenTries = 5000;
Utils.withRetry(this, expectedHttpStatus, maxNumberOfTries, sleepBetweenTries, function(){
// Retry business condition callback
return pm.response.json().length <= 0;
}, function(){
// End retry callback
pm.test("Has one result", function () {
pm.expect(pm.response.json().length).to.equals(0);
});
});
This code will retry request as long as (http statut is different from expectedHttpStatus or businessRetryConditionCallBack is true) AND maxNumberOfTries is not reached and .
When http statut condition is true and maxNumberOfTries is reached, a check is done to verify businessRetryConditionCallBack. If not true, collection execution is stopped.
I have component with a couple of properties, using a promise in the willRender hook to try and create a (pagination) object:
export default Ember.Component.extend({
pagination:null,
testing:null, // to check if this.set is ok within the promise!
willRender() {
let page = {};
let model = this.get('data');
model.get('products').then(relatedItems => {
let maxRecords = relatedItems.get('length');
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
page.Next = relatedItems.objectAt(index+1).get('slug');
}
else if (index+1 === maxRecords) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = null;
}
else {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = relatedItems.objectAt(index+1).get('slug');
}
}
});
this.set('testing','hello world');
console.log(this.get('testing')); // hello world
this.set('pagination',page);
console.log(this.get('pagination')); // Object {Prev: "product-1", Next: "product-2"}
},reject => {
console.log('error '+reject);
});
}
})
In my template
{{testing}} // prints hello world
However, if I try and access {{pagination}} eg {{log pagination}}, the browser crashes with a loop printing out the object to the console.
I don't know where I'm going wrong here - any help much appreciated!
It's likely you are triggering the template to rerender causing willRender to fire over and over which causes an infinite loop in your code.
willRender is a non-standard place to do this code, init would be more standard since it only fires on initialization of the component. Even better would be to use
myInit: Ember.on('init', function(){
....
})`
instead of overriding willRender on the object.
try to check whether Object is present at specific position. i think its going undefined during iteration of for loop. try to ensure that ObjectAt is not returning undefined or null value during running of for loop.
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next == null;
}
}
else if (index+1 === maxRecords) {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
page.Next = null;
}
else {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next = null;
}
}
}
Please ensure that Object at is returning object.
There seems to be a few problems here, would be interested to know what your console errors are.
You don't seem to have defined itemModel so don't know how you're referencing that.
Also you can't access this from within a .then. You need to do something like this to set a component variable.
var _this = this;
promise().then(function(results) {
_this.set('testing', 'hello world');
});
you are not using , after testing:null
there should be , after testing property like that
pagination:null,
testing:null, // i use ',' after testing: null property
try to use your pagination code under init hook rather than willrender hook
init() {
//you code
},
How do I make it resolve the final sum after it has gone through each product?
At the moment return sum; is returning 0. Which I can understand, because this.get('product') is async.
Do I need to use an RSVP? Or other approach?
subtotalInCents: function () {
var sum = 0;
this.get('items').forEach(function(item) {
item.get('product').then(function(product){
sum += item.get('count') * product.get('amountInCents');
console.log(sum);
});
});
return sum;
}.property('items.#each.count'),
Use observer instead.
subtotalInCents: 0,
didItemsChange: function () {
var that = this;
var items = this.get('items');
var itemCount = items.get('length');
var sum = 0;
items.forEach(function(item) {
item.get('product').then(function(product){
sum += item.get('count') * product.get('amountInCents');
itemCount--;
if (itemCount === 0) {
that.set('subtotalInCents', sum);
};
});
});
}.observes('items.#each.count')
This was working for ember-data-0.0.14:
// Used to represent a list of strings, for example the multilocators: [ "43534545354", "4356346" ]
// Used for phone_numers, emails and addresses
// See http://stackoverflow.com/a/18019074/647991
SettingsApp.register('transform:listOfStringsTransform', {
serialize: function(data) {
var elements = [];
for (var i = 0; i < data.length; i++) {
elements.push(data[i]);
}
if (DEBUG) { console.log('listOfStringsTransform.serialize > data=%o -> elements=%o', data, elements); }
return elements;
},
deserialize: function(elements) {
var data = Ember.A();
for (var i = 0; i < elements.length; i++) {
data.push(elements[i]);
}
if (DEBUG) { console.log('listOfStringsTransform.deserialize > elements=%o -> data=%o', elements, data); }
return data;
}
});
But now, I get:
Error while loading route: TypeError: Object #<Object> has no method 'create'
at instantiate (http://localhost:9001/bower/ember/ember.js:10975:26)
at Object.Container.lookup (http://localhost:9001/bower/ember/ember.js:10547:21)
at DS.JSONSerializer.Ember.Object.extend.transformFor (http://localhost:9001/bower/ember-data/ember-data.js:869:36)
at null.<anonymous> (http://localhost:9001/bower/ember-data/ember-data.js:206:28)
at http://localhost:9001/bower/ember-data/ember-data.js:5780:16
at http://localhost:9001/bower/ember/ember.js:3194:16
at Object.OrderedSet.forEach (http://localhost:9001/bower/ember/ember.js:3037:10)
at Object.Map.forEach (http://localhost:9001/bower/ember/ember.js:3192:10)
at Function.DS.Model.reopenClass.eachTransformedAttribute (http://localhost:9001/bower/ember-data/ember-data.js:5779:40)
at DS.JSONSerializer.Ember.Object.extend.applyTransforms (http://localhost:9001/bower/ember-data/ember-data.js:205:10) ember.js:3287
There is a single test for register transform in the ember-data code base, and that is very simple, so it does not work as reference. How can I adapt this working code to the new ember-data?
The transform must be an instance of DS.Transform.extend({})