How to do an "or" in chai should - chai

How do I do an or test with chai.should?
e.g. something like
total.should.equal(4).or.equal(5)
or
total.should.equal.any(4,5)
What's the right syntax? I couldn't find anything in the documentation.

Asserts that the target is a member of the given array list. However, it’s often best to assert that the target is equal to its expected value.
expect(1).to.be.oneOf([1, 2, 3]);
expect(1).to.not.be.oneOf([2, 3, 4]);
https://www.chaijs.com/api/bdd/#method_oneof

Viewing the Chai expect / should documentation, there are several ways to do this test.
Note that you can chain using "and" but apparently not "or" - wish they had this functionality.
Check whether an object passes a truth test:
.satisfy(method)
#param{ Function }matcher
#param{ String }message_optional_
Asserts that the target passes a given truth test.
Example:
expect(1).to.satisfy(function(num) { return num > 0; });
In your case, to test an "or" condition:
yourVariable.should.satisfy(function (num) {
if ((num === 4) || (num === 5)) {
return true;
} else {
return false;
}
});
Check whether a number is within a range:
.within(start, finish)
#param{ Number }startlowerbound inclusive
#param{ Number }finishupperbound inclusive
#param{ String }message_optional_
Asserts that the target is within a range.
Example:
expect(7).to.be.within(5,10);

I have a similar problem to write tests to postman. I solved using the following script:
// delete all products, need token with admin role to complete this operation
pm.test("response is ok and should delete all products", function() {
pm.expect(pm.response.code).to.satisfy((status) => status === 204 || status === 404);
});

Here, I shared exactly what you need to check.
expect(true).to.satisfy(() => {
if (total == 4 || total == 5) return true;
else return false;
});

Because chai assertions throw error you could use try/catch construction:
try {
total.should.equal(4)
} catch (e) {
total.should.equal(5)
}
example of more difficult case:
try {
expect(result).to.have.nested.property('data.' + options.path, null)
} catch (e) {
expect(result).to.have.property('data', null)
}

Related

Karate API : How to assert a json/response node value which returns null or an array object for different data

I've got a request that returns a response node(itemCanBe) value in two possible ways, depending on the 'itemNum'. How do I assert this ? below attempt is not working
* match res..itemCanBe == null || res..itemCanBe[*] contains ['Colgate']
itemCanBe returning null
{
"itemDetails": {
"1234": {
"itemNum": "1234",
"itemCanBe": null
}
}
}
itemCanBe returning array
{
"itemDetails": {
"4567": {
"itemNum": "4567",
"itemCanBe": [
"Colgate",
"Sensodine"
]
}
}
}
See this thread for details: https://github.com/intuit/karate/issues/1202#issuecomment-653632397
This should be good enough to solve your problem.
This will actually work:
* def temp = get[0] response..itemCanBe
* match temp == '##[]'
Also refer: https://stackoverflow.com/a/50350442/143475

Kotlin: function to stop iteration when predicate satisfied

I'm looking for a function in Kotlin which stops an iteration once a predicate is fulfilled:
val services = listOf(service1, service2)
...
var res: Result = null
services.stopIfPredicateFulFilled { service ->
res = service.doSomething()
res != null
}
While this example is not really nice since res is overwritten in each iteration I hope the intention is clear.
forEach doesn't do the job the way I expect it to be done. So, I was wondering if there isn't anything else.
You can use the functions find { ... } and firstOrNull { ... } (they are equivalent, just named differently). They find the first element satisfying the predicate and return that element, ignoring all the remaining elements.
services.find { service ->
res = service.doSomething()
res != null
}

WL JSONStore Sort key <field> is not one of the valid strings

I am having an error when trying to sort doing a findAll:
"Sort key dateis not one of the valid strings."
My options are the following (I tried different formats for desc, everyone was throwing the same 'error'):
var options = {sort: [{"date": "desc"}]};
Everything seems fine, the JSONStore works as expected, sorting the returned data, I just want to be sure that the 'error' is indeed a bug or mistake on the worklight.js part and not that I am doing something wrong.
This is the function that checks for a valid sortObj in worklight.js:
/** Checks if sortObj is a valid sort object for a query
* #private
*/
var __isValidSortObject = function(sortObj, searchFields, additionalSearchFields) {
var propertiesValidated = 0,
sortObjKey, sortStr;
for (sortObjKey in sortObj) {
if (sortObj.hasOwnProperty(sortObjKey)) {
if (propertiesValidated > 0) {
WL.Logger.trace('Sort object ' + JSON.stringify(sortObj) + ' has more than one property. Each object must have only one property.');
return false;
}
//check is sortObjKey is lowerCase
if (_.isUndefined(searchFields[sortObjKey.toLowerCase()]) && _.isUndefined(additionalSearchFields[sortObjKey.toLowerCase()])) {
WL.Logger.trace('Sort key ' + sortObjKey + ' is not part of search fields: ' + JSON.stringify(searchFields) + ' or additional search fields: ' + JSON.stringify(additionalSearchFields));
return false;
}
sortStr = sortObj[sortObjKey];
//Check that the string that specifies sorting order says either "asc" or "desc"
**if (__isString(sortStr) && sortStr.length > 0 && (/^(a|de)sc$/i.test(sortStr))) {
WL.Logger.trace('Sort key ' + sortObjKey + 'is not one of the valid strings.');
propertiesValidated++;
} else {
// Here seems to be the problem, shouldn't the trace be before return false?
return false;
}**
}
}
if (propertiesValidated === 0) {
return false;
}
return true;
};
You can clearly see that they do the WL.Logger.trace when the check is fine and that it should be just before return false.
Does anyone that has used sort on a JSONStore receives this trace as well?.
Platform version: 7.1.0.00.20160129-1923
I contacted IBM support and they indeed confirmed that it is a bug that will be solved in the next build.

Functional testing conditionals with Intern/Leadfoot

I am wishing to conditionally execute some commands/assertions depending on whether previous assertions succeeded or not.
I can't seem to find a way to nest then calls or conditionally execute things using the chaining syntax of leadfoot.
Here is my test (the returns at the end of each function is due to this being compiled coffeescript):
tdd.test(tableUrl, function() {
this.timeout = 60000;
return this.remote.get(require.toUrl("tests/pages/" + tableUrl))
.setPageLoadTimeout(60000)
.setFindTimeout(20000)
.findByCssSelector('.dataTables_wrapper table.dataTable')
.then(null, function(err) {
return assert.fail('', '', 'Table should exist');
}).then(pollUntil(function() {
var table;
table = document.querySelector('.dataTables_wrapper table.dataTable');
if (table.querySelectorAll('tbody td').length > 1) {
return true;
} else {
return null;
}
}, null, 20000, 500)).then(function() {
console.log('Assertion succeeded: Table should have data');
return assert.ok(true, 'Table should have data');
}, function(err) {
return assert.fail('', '', 'Table should have data');
});
});
When a table does not exist, both 'Table should exist' and 'Table should have data' assertions should be reported as failing. However, only the last assertion is failing. When I comment out the 'Table should have data' error callback, the 'Table should exist' assertion is reported as failing correctly.
What I would like to do is
test if a table exists (via findByCssSelector).
a) If it exists, report that it exists and test to see that it has more than one td element. This is currently done via pollUntil to ensure that the command is complete/promise is resolved as soon as more than one td is found instead of waiting for the whole implicit wait time.
b) If it does not exist, report that it does not exist.
I can't seem to find a way of not executing the error callback of the second 'Table should have data' poll if the first findByCssSelector fails, due to lack of conditionals and only the last assertion failure being reported in a test.
So conditional branching can happen with then calls, this answer addresses how to do conditional branching with intern.
The problem I was having was the pollUntil function not behaving the same way as a normal leadfoot Command method due to the function returning a callback function that returns a promise rather than a promise directly.
This can be circumvented by wrapping the pollUntil in an anonymous function, immediately calling the pollUntil function using the call method, passing in the current this value due to then setting the context of the callback to the Command object, and then finally chaining another Command.
This is what the above code turned into using correct conditional branching with pollUntil.
tdd.test(tableUrl, function() {
this.timeout = 60000;
return this.remote.get(require.toUrl("tests/pages/" + tableUrl))
.setPageLoadTimeout(60000)
.setFindTimeout(5000)
.findByCssSelector('.dataTables_wrapper table.dataTable')
.then((function() {
return pollUntil(function() {
var table;
table = document.querySelector('.dataTables_wrapper table.dataTable');
if (table.querySelectorAll('tbody td').length > 1) {
return true;
} else {
return null;
}
}, null, 20000, 500).call(this).then(function() {
console.log('Assertion succeeded: Table should have data');
return assert.ok(true, 'Table should have data');
}, function(err) {
return assert.fail('', '', 'Table should have data');
});
}), function(err) {
return assert.fail('', '', "Table should exist. Error: " + err.name);
});
});

KnockoutJS throttle input

I'm trying to implement something like a typesafe ViewModel using KnockoutJS. It works pretty well until I start to update observables via HTML input tags.
I have implemented type extender which returns computed observable:
return ko.computed({
read: target,
write: fixer
})
Where fixer is something like:
function (newValue) {
var current = target(),
valueToWrite = (newValue == null ? null : fixNumber(newValue, 0));
if (valueToWrite !== current) target(valueToWrite);
else if (newValue !== current) target.notifySubscribers(valueToWrite);
}
And fixNumber is
function fixNumber(value, precision) {
if (value == null || value === '') return null;
var newValue = (value || '').toString().replace(/^[^\,\.\d\-]*([\.\,\-]?\d*)([\,\.]?\d*).*$/, '$1$2').replace(/\,/, '.'),
valueToWrite = Number(newValue);
return !!(valueToWrite % 1) ? round(valueToWrite, precision) : valueToWrite;
}
It looks not so straightforward, but I have to consider possible use of comma as a decimal separator.
Often I need to update my observables as soon as user presses key to reflect this change immediately:
<input type="text" data-bind="value: nonThrottled, valueUpdate: 'afterkeyup'"></input>
And here comes a lot of problems, because, for example, I can't input decimal values less than 1 (0.1, 0.2, etc) there.
When I try to throttle an observable it mostly works. But sometimes user input and type fixer go out of sync, so it looks like some input gets lost occasionally.
Full example is there http://jsfiddle.net/mailgpa/JHztW/. I would really appreciate any hints, since I have spent days trying to fix these problems.
UPDATE 11/04/2013
I solved my problem providing custom value binding, so now throttled observables doesn't eat my input occasionally.
I've added additional valueThrottle option-binding to throttle updating of element's value:
var valueThrottle = allBindingsAccessor()["valueThrottle"];
var valueThrottleTimeoutInstance = null;
/* ... */
if (valueThrottle) {
clearTimeout(valueThrottleTimeoutInstance);
valueThrottleTimeoutInstance = setTimeout(function () {
ko.selectExtensions.writeValue( element, ko.utils.unwrapObservable(valueAccessor()) );
}, valueThrottle);
} else applyValueAction();
Also I've noticed that inability to enter values like 0.2 in my case comes from that statement in original value binding:
if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
valueHasChanged = true;
I've rewritten it as
if ((newValue === 0) && (elementValue != 0))
valueHasChanged = true;
It works at least at Chrome, but I haven't tested it properly and even not sure that it's correct.
Example is to be added, for some reason jsFiddle does not accept my custom binding.
Any comments are really appreciated.