How to set variables inside a mocha test - javascript

I am having trouble understanding how to set variables for use in my tests. For example I have a function called spark.isTriple() that takes a number and looks at an array called dice and returns true if the value occurs three or more times or false if it doesn't.
#In game.coffee
window.spark =
isTriple: (n)->
triples = _.filter dice, (i)->
n is i
if triples.length >= 3
true
else
false
And I have a test that looks like this.
# In game_spec.coffee
describe 'spark.isTriple', ->
it "Should return true if the given value is found 3 or more times in the dice roll", ->
dice = [1,2,2,2,4,5]
spark.isTriple(2).should.be.true
The problem is that 'dice' is also being set in an earlier test that is actually testing a rollDice() function. In that test dice is being set to a random array of values which is what it should be doing and testing. But for this particular test I want to be able to set 'dice' to a specific array in order to test my isTriple() function. I've tried placing the "dice = [1,2,2,2,3,4]" in a before() call and a beforeEach() call but it doesn't seem to make any difference.
If anyone can give me some help or pointers on this it would be much appreciated.

So mocha + coffeescript sometimes requires an explicit declare in the right scope if you want a variable that a whole suite of tests can use and can be manipulated during before/beforeEach/after/afterEach.
describe 'spark.isTriple', ->
dice = null #force coffeescript var declaration
it "should blah blah", ->
dice = [1,2,2,2,4,5]
I'm pretty sure something along those lines will fix your problem, but if you post a full file that demonstrates the issue I can be sure.

I'm gonna disagree with Peter here. I think depending on a variable across tests is a bad idea -- it sets you up for intermittent and weird failures in tests. Anything that's going to change as a result of the test should be contained only in that test. To that end, I'd write your re-write your code like so (from the coffee console):
window.spark = hasTriple: (dice, n) ->
ld.filter(dice, ((i) -> n is i)).length >= 3
{ hasTriple: [Function] }
coffee> window.spark.hasTriple([1,2,1,2,5,6], 2)
false
coffee> window.spark.hasTriple([1,2,2,2,5,6], 2)
true
I renamed _ to ld (aka Lodash) because _ has a special meaning in the console so I think it's a good practice to avoid using it.

Related

Haskell Webviewhs textfields and returns to Haskell

I've discovered webviewhs and tried it recently. It just works and I think it can do what I need it to do. Samples are abundant, but I would need some pointers of Haskell experts.
{-# LANGUAGE
OverloadedStrings
, QuasiQuotes
#-}
import Data.Text
import Language.Javascript.JMacro
import qualified Graphics.UI.Webviewhs as WHS
main :: IO ()
main =
WHS.withWindowLoop
WHS.WindowParams
{ WHS.windowParamsTitle = "webviewhs - How do I run some JavaScript inside the window?"
-- This could be a localhost URL to your single-page application (SPA).
, WHS.windowParamsUri = ""
, WHS.windowParamsWidth = 800
, WHS.windowParamsHeight = 600
, WHS.windowParamsResizable = True
, WHS.windowParamsDebuggable = True
}
-- This is the callback JavaScript can execute.
(\ _window stringFromJavaScript -> print stringFromJavaScript) $
-- This function runs every window loop.
-- Return True to continue the loop or False to exit the loop.
\ window -> do
let string = "Hello from Haskell." :: Text
-- runJavaScript returns either True on success or False on failure.
WHS.runJavaScript
window
[jmacro|
alert ("Yahoo! Alert windows, but little too persistent!");
window.external.invoke("Hello from JavaScript.");
|]
If I use the code above, the alert-dialog (test) keeps popping up. I would love to have it gone after ok. I also tried several times to get information (document.getElementById) from a sites' input field. Cannot get that to work. For me webviewhs is the missing link in Haskell and I would really like to get it to work.
The problem is in WHS.withWindowLoop. Referring to the documentation:
Creates a window for you. Accepts a function that is called with each iteration of the window loop. If the accepted function returns False, the loop is exited and the window is destroyed. If the accepted function returns True, the loop is continued provided it can.
(my emphasis)
Note that the last parameter of withWindowLoop is invoked repeatedly until it returns False. However, you are always returning True, meaning that the dialog box is repeatedly opened without ever finishing the loop. I can see two ways out of this problem:
Use WHC.createWindow instead; this function simply creates a window and returns it, without looping. This is the approach used in the relevant example.
Keep on using withWindowLoop, but return False instead of True. This will stop the loop immediately after one iteration.
If you really want to use withWindowLoop, then you could declare an IORef which is True at first, then changed to False after one iteration. That approach isn't very idiomatic though. (Don't use this approach, it doesn't work, it actually launches the dialog box twice, and it's much more complicated than needed anyway)

How to test a function that output is random using Jest?

How to test a function that output is random using Jest? Like this:
import cuid from 'cuid';
const functionToTest = (value) => ({
[cuid()]: {
a: Math.random(),
b: new Date().toString(),
c: value,
}
});
So the output of functionToTest('Some predictable value') will be something like:
{
'cixrchnp60000vhidc9qvd10p': {
a: 0.08715126430943698,
b: 'Tue Jan 10 2017 15:20:58 GMT+0200 (EET)',
c: 'Some predictable value'
},
}
I used:
beforeEach(() => {
jest.spyOn(global.Math, 'random').mockReturnValue(0.123456789);
});
afterEach(() => {
jest.spyOn(global.Math, 'random').mockRestore();
})
It is easy to add and restores the functionality outside the tests.
Here's what I put at the top of my test file:
const mockMath = Object.create(global.Math);
mockMath.random = () => 0.5;
global.Math = mockMath;
In tests run from that file, Math.random always returns 0.5.
Full credit should go to this for the idea: https://stackoverflow.com/a/40460395/2140998, which clarifies that this overwrite is test-specific. My Object.create is just my additional extra little bit of caution avoiding tampering with the internals of Math itself.
I've taken Stuart Watt's solution and ran with it (and got a bit carried away). Stuart's solution is good but I was underwhelmed with the idea of having a random number generator always spit out 0.5 - seems like there would be situations where you're counting on some variance. I also wanted to mock crypto.randomBytes for my password salts (using Jest server-side). I spent a bit of time on this so I figured I'd share the knowledge.
One of the things I noticed is that even if you have a repeatable stream of numbers, introducing a new call to Math.random() could screw up all subsequent calls. I found a way around this problem. This approach should be applicable to pretty much any random thing you need to mock.
(side note: if you want to steal this, you'll need to install Chance.js - yarn/npm add/install chance)
To mock Math.random, put this in one of the files pointed at by your package.json's {"jest":{"setupFiles"} array:
const Chance = require('chance')
const chances = {}
const mockMath = Object.create(Math)
mockMath.random = (seed = 42) => {
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
return chance.random()
}
global.Math = mockMath
You'll notice that Math.random() now has a parameter - a seed. This seed can be a string. What this means is that, while you're writing your code, you can call for the random number generator you want by name. When I added a test to code to check if this worked, I didn't put a seed it. It screwed up my previously mocked Math.random() snapshots. But then when I changed it to Math.random('mathTest'), it created a new generator called "mathTest" and stopped intercepting the sequence from the default one.
I also mocked crypto.randomBytes for my password salts. So when I write the code to generate my salts, I might write crypto.randomBytes(32, 'user sign up salt').toString('base64'). That way I can be pretty sure that no subsequent call to crypto.randomBytes is going to mess with my sequence.
If anyone else is interested in mocking crypto in this way, here's how. Put this code inside <rootDir>/__mocks__/crypto.js:
const crypto = require.requireActual('crypto')
const Chance = require('chance')
const chances = {}
const mockCrypto = Object.create(crypto)
mockCrypto.randomBytes = (size, seed = 42, callback) => {
if (typeof seed === 'function') {
callback = seed
seed = 42
}
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
const randomByteArray = chance.n(chance.natural, size, { max: 255 })
const buffer = Buffer.from(randomByteArray)
if (typeof callback === 'function') {
callback(null, buffer)
}
return buffer
}
module.exports = mockCrypto
And then just call jest.mock('crypto') (again, I have it in one of my "setupFiles"). Since I'm releasing it, I went ahead and made it compatible with the callback method (though I have no intention of using it that way).
These two pieces of code pass all 17 of these tests (I created __clearChances__ functions for the beforeEach()s - it just deletes all the keys from the chances hash)
Update: Been using this for a few days now and I think it works pretty well. The only thing is I think that perhaps a better strategy would be creating a Math.useSeed function that's run at the top of tests that require Math.random
I'd ask myself the following questions:
Do I really need to test random output? If I have to, I'd most likely test ranges or make sure that I received a number in a valid format, not the value itself
Is it enough to test the value for c?
Sometimes there is a way to encapsulate the generation of the random value in a Mock and override the generation in your test to return only known values. This is a common practice in my code. How to mock a constructor like new Date() sounds like a similar approach in jestjs.
You could always use jest-mock-random
But it offers a little bit more functionality than mocking it as proposed in the first answer.
For example you could use before the testmockRandomWith(0.6); and your Math.random in test will always return this predictable value
Mocking literal random data isn't exactly the way to test. The question is, as it's stated, is a bit broad because "how to test a function that output is random" requires you to do statistical analysis of the output to ensure effective randomness - which has likely been done by the creators of your pseudo-random number generator.
Inferring instead "that output is random" means you want to ensure the function functions properly regardless of the random data then merely mocking the Math.random call to return numbers that meet your specific criteria (covering any variance) is enough. That function is a third-party boundary that, while needing testing, is not what's being tested based on my inference. Unless it is - in which case refer to the paragraph above.
I agree with Richard Barker answer. Strange that at the time of writing his answer has 0 votes, while the upvoted and accepted ones completely miss the point. Guess this thread is too old.
How to test a function that output is random using Jest? Its not a Jest or even a programming problem, but a statistical (or even philosophical) one and as far as I can understand, mathematics can only conclusively prove that a sequence is non-random, meaning it has a recognizable pattern. Math.random() as all other pseudo-random number generators will eventually put out a pattern, cause they are algorithms.
The best actionable advice is in cringe answer. Test the return range and type. All other suggestions eliminate the output randomness that is supposedly being tested, making the "test for randomness" pointless.

Shiny and Javascript - Uncaught ReferenceError: TRUE is not defined

I have a shinyapp which has a basic login screen.
When the app loads, the "Logged" variable is FALSE. When the user successfully logs in within the session, the R login code is as follows:
X$Logged <- TRUE
At this point, in the javascript console I get warnings saying "Uncaught ReferenceError: TRUE is not defined".
I click on the link to go to the code, and the javascript code is:
(function() {
with (this) {return (X$Logged=TRUE);}
})
I am a beginner. I am assuming that firstly, this is the javascript render of my R code above, and secondly that it doesn't like it because javascript expects a lower case boolean "true".
How can I get around this? Equally, R doesn't like lower case boolean.
How can I get around this? Equally, R doesn't like lower case boolean.
Define one in the other, e.g. as you're going to JavaScript, before your code (in the JavaScript)
var TRUE = true, FALSE = false;
Then
(function() {
with (this) {return (X$Logged=TRUE);} // should now work
})
Alternatively, you could use bool-like things, i.e. 1 and 0 instead.
Finally, how are you doing the R to JS transformation? This well may be a bug in the framework you've used
Paul's and Mritunjay's answer helped me to get this fixed.
The misunderstanding was in a conditionalPanel() within my ui.R file. I had:
conditionalPanel(
condition="X$Logged=TRUE"
...
)
I spotted the single "=" instead of "==" and realised the condition within the inverted commas is JS, and not R. I therefore changed my ui.R to this:
conditionalPanel(
condition="X$Logged=true"
...
)
However, I kept upper case "TRUE" in all of my server.R logic, like this:
X$Logged <- TRUE
...and it now works.

Get argument expression before evaluation

I'm trying to create an assert method in Javascript. I've been struggling with arguments.callee.caller and friends for a while, but I can't find a way to reliably get the full text of the calling function and find which match in that text called the current function.
I want to be able to use my function like this:
var four = 5;
function calculate4() { return 6; }
assert(4 == 2 + 3);
assert(4 == four);
assert(4 == calculate4());
assert(4 != 3 && 2 < 1)
and get output like this:
Assertion 4 == 2 + 3 failed.
Assertion 4 == four failed.
Assertion 4 == calculate4() failed.
Assertion 4 != 3 && 2
Right now, I can't get much beyond Assertion false failed. which isn't very useful...
I'd like to avoid passing in extra parameters (such as this) because I want to keep the assert code as clean as possible and because it will be typed many, many times. I don't really mind making it a string, but I'm concerned about issues of scoping when trying to eval() that string. If I have no other options, or if my concerns are ill-founded, please say so.
I'm running this in an .hta application on Windows, so it's really jscript and I have full access to the filesystem, ActiveX etc. so system specific solutions are fine (as long as they don't require Firebug etc.). However, I'd prefer a general solution.
There's no reliable way you can do this passing only a single argument. Even with eval, the variables used would be out of scope. Parsing arguments.caller would work if arguments.caller made only one call to assert, by searching for it and parsing the argument expression. Unfortunately, none of the proprietary tools available to you will help.
I ended up using the following function, which allows me to optionally duplicate the text of the assertion as a second argument. It seemed simplest.
function assert(expression, message)
{
if (!expression) {
if (message + "" != "undefined" && message + "" != "") {
document.write("<h2>Assertion <pre>" +
message +
"</pre> failed.</h2><br>");
} else {
document.write("<h2>Assertion failed.</h2><br>");
}
}
}
Maybe that helps someone. There are probably better methods available, but this worked for me.
Note that I've only been programming in Javascript for three days, so there's probably a number of improvements that could be made.
It is actually possible, at least in browsers and Node.js. I don't know about .hta applications.
Modern browsers, Node.js and hopefully your environment put a stack property on error objects, containing a stack trace. You can construct a new error, and then parse out the file path to the file containing the assert() call, as well as the line number and column number (if available) of the call. Then read the source file, and cut out the assert expression at the given position.
Construct an error
Parse error.stack, to get filepath, lineNumber and columnNumber
Read the file at filepath
Cut out the bits you want near lineNumber and columnNumber in file
I've written such an assert function, called yaba, that might get you going.

Why am I seeing inconsistent JavaScript logic behavior looping with an alert() vs. without it? [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 6 years ago.
I have code similar to this filtering entries in an Array of Objects:
var filterRegex = new RegExp(".*blah.*","ig");
if (filterRegex.test(events[i].thing) && events[i].show) {
console.log("SUCCESS: filtering thing " + i + " " + events[i].thing);
events[i].show = false;
numevents--;
}
I get inconsistent results with this if condition (checking with Firebug, both conditions are true individually, but sometimes the whole expression evaluates to false). HOWEVER, if I actually put an alert() called inside this if statement (like line 4), it becomes consistent and I get the result I want.
Can you see anything wrong with this logic and tell me why it's not always producing what is expected?
Ok, i see it now. The key to your problem is the use of the g (global match) flag: when this is specified for a regex, it will be set up such that it can be executed multiple times, beginning each time at the place where it left off last time. It keeps a "bookmark" of sorts in its lastIndex property:
var testRegex = /blah/ig;
// logs: true 4
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: true 9
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: false 0
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
The above example creates an instance of a very simple regex: it matches "blah", upper or lower case, anywhere in the string, and it can be matched multiple times (the g flag). On the first run, it matches the first "blah", and leaves lastIndex set to 4 (the index of the space after the first "blah"). The second run starts matching at the lastIndex, matches the second blah, and leaves lastIndex set to 9 - one past the end of the array. The third run doesn't match - lastIndex is bogus - and leaves lastIndex set to 0. A fourth run would therefore have the same results as the first.
Now, your expression is quite a bit more greedy than mine: it will match any number of any characters before or after "blah". Therefore, no matter what string you test on, if it contains "blah" it will always match the entire string and leave lastIndex set to the length of the string just tested. Meaning, if you were to call test() twice, the second test would always fail:
var filterRegex = /.*blah.*/ig;
// logs: true, 9
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: false, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
Fortunately, since you create your regex immediately prior to calling test(), and never call test() more than once, you'll never run into unexpected behavior... Unless you're using a debugger that lets you add in another call to test() on the side. Yup. With Firebug running, a watch expression containing your call to test() will result in intermittent false results showing up, either in your code or in the watch results, depending on which one gets to it first. Driving you slowly insane...
Of course, without the g flag, livin' is easy:
var filterRegex = /.*blah.*/i;
// logs: true, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: true, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
Suggestions
Avoid the global flag when you don't need it.
Be careful what you evaluate in the debugger: if there are side effects, it can affect the behavior of your program.
I just can't imagine there is any situation where two JavaScript expressions evaluate to true individually, but not when combined.
Are you sure both expressions actually produce a boolean value every time? (Okay, to make regex.test() not produce a boolean value is difficult, but how about event.show. Might that be undefined at times?
Do you refer to the correct index when saying event[0].show, wouldn't you mean event[i].show?
That's seems you are facing some kind of race conditions with the event array, that's why when you use the alert() everything works fine.

Categories

Resources