custom test function - JS - javascript

I want to create a function like below.
This is the expect function of jest. I want to create this function in Javascript.
Is this do-able??
let type = 'apple'
expect(type).toBe('apple')
//pass a string to "expect" function and it checks with 'toBe' function if the string is similar
Update: I know we can do something like below but i am unable to do something like this "expect().toBe()"
var Expect = Expect || {};
Expect.String = function() {
var toBe = "tobe";
var toBe = function() {
console.log("toBE function");
};
return {
toBe: toBe
}
}()
Expect.String.toBe(); // this will log "toBe function"

This is just a small example of what you are likely going for. You want expect to be a function that returns an object where one of the keys, toBe, is a function. In this example, I just have it returning true or false depending on whether the actual equals expected value.
function expect(actual) {
return {
toBe: function(expected) {
return actual === expected;
}
}
}
console.log(
expect("foo").toBe("foo")
);
console.log(
expect("foo").toBe("bar")
);

It is recommended to not reinvent the wheel, but since you are already there, here is what I recommend in a nutshell:
The function expect() takes a first thing(a.k.a actual) and returns an object that contains yet another function: toBe()
The function toBe() takes second thing (a.k.a expected) as a parameter, uses some form of comparator against the first thing, and returns a boolean
For simplicity, the comparator can be ==
Based on these three elements, Your re-invented expect() function can take the alike of the following shape:
function expect(actual){
return {
toBe: function(expected){
return actual == expected;
}
}
}
The actual implementation is a little more complicated than this answer ~ For the real-world implementation of expect in Jest is at this GitHub address
The "matchers" (as they call alikes of toBe(), toEqual(), etc) can also be found in this source code

Related

Chaining member variables with side-effect with the chain not ending in a function

In the JavaScript chaijs testing library it is possible to chain members like this:
pm.expect (entry.NAME).to.be.a('string').that.is.not.empty;
This question is not about the testing library, but about the library's internal technique. I understand it works something like this: pm.expect is a function that returns an object that contains at least { to: { be: { a } } } where a is another function that returns at least { that: { is: { not: { empty } } } }.
The interesting thing is that empty apparently is not a function. If it was, I would have to call it like this: that.is.not.empty() (note the parentheses). So the chain ends with a member variable that is not a function.
How is it possible in JavaScript to consume that member variable to cause a side-effect? Can you show me a minimal JS snippet that allows me to end an expression with something that is not a function call (like empty;) and still act like it was a function call?
function expect(value) {
return {
get empty() { return !value.length; },
};
}
expect("test").empty // false
expect("").empty // true
That's done with a getter, have a look at the ChaiJS sourcecode.
Can you show me a minimal JS snippet that allows me to end an expression with something that is not a function call (like empty;) and still act like it was a function call?
Sure. One way is to use a getter:
const person = (name) => ({
get greet() { return `Hello ${name}!`; },
get dismiss() { return `Goodbye ${name}!`; }
});
console.log( person("Tyler").greet );
console.log( person("John").dismiss );

Is there a backwards compatible way to update a library to use getters?

Assuming a library with a function like:
class Stuff {
total () {
return 4; // might be some calculation
}
}
But you want to update it to use a getter, like:
class Stuff {
get total () {
return 4;
}
}
Is there a way to make a change like this in a backwards compatible way? So code that uses the library assuming a function doesn't break?
stuff.total // should work with new version
stuff.total() // hopefully this still works
Edit: This question is more about library evolution (more general). The other one is about a particular solution and from a call-site perspective.
You should not do this. stuff.total should either be a number or a function, but not both. That will make for very confusing and difficult to maintain code in the future.
That said, you can do something along the lines of what you want:
class Stuff {
get total () {
const callable = function ( ) {
return 4;
};
callable[Symbol.toPrimitive] = callable;
return callable;
}
}
const stuff = new Stuff;
console.log( stuff.total );
console.log( stuff.total( ) );
console.log( 1 + stuff.total );
console.log( 1 + stuff.total( ) );
// stuff.total is a function, not a number!
console.log( typeof stuff.total );
console.log( stuff.total.toString( ) );
// But if it's implicitly coerced to a string, it's toString is not called:
console.log( '' + stuff.total);
console.log( `${stuff.total}` );
There are some caveats though. stuff.total is a getter here that is returning a function, not a number. Using that function anywhere a primitive is expected results in the function being called and it's return value being used instead, but it is still really a function. That is evident when you log stuff.total.toString( ) or typeof stuff.total.
The answer is mostly "no", but partly "it depends".
It comes down to how the existing code is going to use the result. In some cases, you could make a getter work by returning a function, but not in other cases.
Your code example shows a function that returns a simple primitive number, which makes things a little more difficult. In cases where the getter's result is used in such a way that its .valueOf() method will be automatically invoked, you can get the desired behavior if you return a function with the .valueOf() overridden.
class Doer {
get total () {
var f = function() { return f.valueOf() };
f.valueOf = function() { return 4 };
return f
}
}
const d = new Doer();
const x = 10 + d.total();
const y = 10 + d.total; // The addition forces the .valueOf() evaluation
console.log(x, y);
However d.total is still ultimately a function and not the number 4.
If you were returning an object, you could perhaps fake it a bit more easily by returning an object that inherits from Function.prototype, but still it will greatly depend on the actual usage.

How to print arguments' list in javascript?

Is there a way to print arguments' list in full or in parts in JavaScript?
Example:
from within the function my_assert(a!=b) I'd like to print a!=b, or even 2!=3 for a particular function call.
you can't. a!=b is executed first and only the result of this (true or false) is given to your function so you don't have a chance to get back a!=b or 2!=3.
console.log (arguments)
will print the arguments given to the function, but in your case, all your function sees is a boolean, because a != b will be evaluated first, and only the result passed as a parameter in the function call.
umm... here, I'll google it for you :)
http://www.seifi.org/javascript/javascript-arguments.html
As some others pointed out, passing in a test (a != b) will only get you a boolean value (true|false) as your argument. But if you call myAssert(a,b), you can then evaluate the arguments and test their equality, as well as print their values, following the advice in the link I pasted.
Here you go:
my_assert = (test) ->
str = my_assert.caller.toString()
match = /return my_assert\((.*)\)/.exec str
console.log match[1], test
a = '1'
b = '2'
do -> my_assert(a!=b)
do -> my_assert(b!=a)
> a !== b true
> b !== a true
http://jsfiddle.net/m7qRN/
The only caveat is you have to call your my_assert calls from separate anonymous functions in order to be able to reliably get the source code of the assertion call.
In CoffeeScript its not so bad using the do -> notation.
In JS this is: (function(){my_assert(a!=b)})();.
You could pass in the test as a function like so:
my_assert -> a!=b
my_assert(function(){a!=b});
//
// A variation on vaughan's answer, from Oct 1 '13
// Includes simple unit test to debug the regex for multiline assert expressions
// Use console.error and/or 'throw new Error' depending how you handle errors
//
function test_assert() {
try {
(function () { assert(3 === 'a') })();
(function () {
assert('foo' !== 'bar')
})();
(function () {
assert('foo' ===
'bar')
})();
} catch (e) {
console.error(e.stack)
}
} // test_assert
function assert(expression) {
if (!expression) {
let caller = assert.caller.toString()
let test = caller.match(/assert[^]*\)/)
//throw new Error(test[0] + ' failed');
console.error('%s failed', test[0])
}
} // assert
/////////////////////////////////
// Here's a simple assert()
function assert2(condition, message) {
if (!condition) {
console.error('assert (%s) failed: "%s"', condition, message)
throw new Error("Assertion failed: " + message);
}
}
You can't do it. When you have the following line:
my_assert(a!=b);
The expression a!=b will first be evaluated and its result will be passed to my_assert.
Assuming your my_assert() function is used specifically for your own testing and you can control how it works and what you pass into it you could do something like this:
my_assert(a!=b, "a!=b");
I.e., pass an extra parameter to the function with a string representation of what is being tested. Obviously that doesn't stop you accidentally saying my_assert(a!=b, "a==b");, and it's clunky, but I can't think of another way to do it.

Can a JavaScript function return itself?

Can I write a function that returns iteself?
I was reading some description on closures - see Example 6 - where a function was returning a function, so you could call func()(); as valid JavaScript.
So I was wondering could a function return itself in such a way that you could chain it to itself indefinitely like this:
func(arg)(other_arg)()(blah);
Using arguments object, callee or caller?
There are 2-3 ways. One is, as you say, is to use arguments.callee. It might be the only way if you're dealing with an anonymous function that's not stored assigned to a variable somewhere (that you know of):
(function() {
return arguments.callee;
})()()()().... ;
The 2nd is to use the function's name
function namedFunc() {
return namedFunc;
}
namedFunc()()()().... ;
And the last one is to use an anonymous function assigned to a variable, but you have to know the variable, so in that case I see no reason, why you can't just give the function a name, and use the method above
var storedFunc = function() {
return storedFunc;
};
storedFunc()()()().... ;
They're all functionally identical, but callee is the simplest.
Edit: And I agree with SLaks; I can't recommend it either
Yes.
Just return arguments.callee;
However, this is likely to result in very confusing code; I do not recommend it.
You can do what you want as following:
// Do definition and execution at the same time.
var someFunction = (function someFunction() {
// do stuff
return someFunction
})();
console.log(someFunction)
arguments.callee is not supported in JavaScript strict mode.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
Even sorter that all the above is:
f=()=>f
There is a simple way to achieve this doing the following:
let intArr = [];
function mul(x){
if(!x){
return intArr.reduce((prev, curr) => prev * curr)
}
intArr.push(x);
return mul;
}
console.log(mul(2)(4)(2)()); => outputs 16
It is also possible just to return the argument the self invokable function like
console.log( (function(a) { return a; })(1) ); // returns 1

How can implement overloading in JavaScript/jQuery?

Im trying to call functions with same signature.
Example: There are two functions with same name:
<script>
var obj1,obj2,obj3,obj4,obj5;
function OpenBox(obj1,obj2){
// code
}
function OpenBox(obj1,obj2,obj3,obj4,obj5){
// code
}
</script>
When I calling function on click event of link
<a id='hlnk1' href='#' onclick='OpenBox(this,\"abhishek\"); return false;'> Open Box </a>
When I click on the above link it is calling function OpenBox(obj1,obj2,obj3,obj4,obj5){}
It should be call function OpenBox(obj1,obj2){} Instead.
What's going wrong in functions?
mattn has the correct idea. Because javascript has no typing those functions are equivalent. What you could do is something like this:
function OpenBox_impl1(obj1,obj2){
// code
}
function OpenBox_impl2(obj1,obj2,obj3,obj4,obj5){
// code
}
function OpenBox(obj1, obj2, obj3, obj4, obj5) {
if(arguments.length == 2)
return OpenBox_impl1(obj1, obj2);
else
return OpenBox_impl2(obj1,obj2,obj3,obj4,obj5);
}
javascript can't define duplicate function in same scope. check arguments.length are 2 or 5.
You cannot overload functions in JavaScript. Instead, the most recently defined version of the function will be used, which is why in your case the version with 5 parameters is called (the final 3 are just undefined).
There are several ways around this, one if which is shown in Mikola's answer. An alternative is to pass in an object, and then check the contents of that object in the function (see this question):
function foo(a, b, opts) {
}
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
Another option is to check arguments.length:
function foo(a, b) {
if(arguments.length > 2) {
var arg3 = arguments[3];
//etc...
}
}
in the polymorphism you can use a different signature method ,in javascript we can simulate polymorphism checking the type of the function parameter and execute certain task.
var input = document.getElementById('data');
polymorphism(input);
polymorphism('Hello word 2');
polymorphism('hello word 3', 5);
function polymorphism(arg,arg1){
var string = null;
var sqr = 0;
if(typeof arg === 'string'){
string = 'arg type String: \n'+arg;
}else if (arg.tagName && arg.tagName === 'INPUT'){
string = 'arg type Input: \n'+arg.value;
}
if(arg1 && typeof arg1 === 'number'){
sqr = arg1*arg1;
alert(string + ' and sqr = '+sqr);
}else {
alert(string);
}
}
Check this example in JSFIDDLE
#abshik ,
There is nothing like that which is similar to c# or java. Javasccript behaves this way
function Test(arg1 ,arg2 , arg3, arg4)
{
}
when you are calling this function you can call in the following ways
Test(arg1);
Test(arg1,arg2);
Test(arg1,arg2,arg3);
Test(arg1,arg2,arg3,arg4);
But sequence matters , so you can the function in the above ways.
The issue is that you are trying to overload a function but that is not supported by Javascript. I think your best option is to use Polymorphism instead. View this article for more details: http://www.cyberminds.co.uk/blog/articles/polymorphism-in-javascript.aspx
Once a function is defined in ecmascript, that name is locked. However, you can pass any number of parameters to that function so you do the rest of the work on the inside.
function foo(arg1, arg2) {
// any code that is needed regardless of param count
if(arg2 !== undefined) {
// run function with both arguments
console.log(arguments);
} else if(arg1 !== undefined) {
// run function with one argument
} else {
// run function with no arguments
}
}
foo(1);
foo(1,2);
foo(1,2,3);
Interesting note: you can pass in extra parameters that aren't in the function declaration. Do a console.log of arguments and you'll see everything in there. arguments is an object which can be accessed like / typecasted to an array.

Categories