I'm writing unit tests for a simple javascript...
Karma v1.5.0
Jasmine v2.5.3
PhantomJS v2.1.14
I'm trying to write a test to ensure that a cookie is getting the proper expiration date (30 days). Recent versions of Jasmine support faking the passage of time using jasmine.clock() but this doesn't appear to work on cookie expiration...
describe("cookies...", function () {
it("expire after 30 days", function () {
jasmine.clock().install();
set_a_cookie_to_expire_in_30_days();
jasmine.clock().tick(29 *24*60*60*1000); //fast forward 29 days
expect(check_cookie()).toBeTruthy();
jasmine.clock().tick(2 *24*60*60*1000); //fast forward another 2 days
expect(check_cookie()).toBeFalsy(); //THIS FAILS
jasmine.clock().uninstall();
});
});
The second expect() fails. What am I doing wrong?
The Jasmine clock tick won't actually affect time passing in the browser. It will only execute callbacks for setTimeouts or setIntervals.
From their docs:
The Jasmine Clock is available for a test suites that need the ability to use setTimeout or setInterval callbacks. It makes the timer callbacks synchronous, executing the registered functions only once the clock is ticked forward in time. This makes timer-related code much easier to test.
You should instead use mockDate.
jasmine.clock().mockDate(
new Date(2018, 5, 11)
);
Where you tick forward 29 days, you can simply mockDate again 29 days forward. Hope this helps!
Related
I will be gone for a weekend and I need a node.js file to run at a specific time and date. I have not found any way to do this through javascript, but apparently cron works (I am running linux).
I created an sh file that runs the nod.js file and had it run through cron, but it did not run at all. I don't know if this has anything to do with Puppeteer + Node.js, but no script ran...
I also tried using the at command but that did not work either
For cron, I added the line:
20 14 2 5 * ~/.../start.sh
The sh file was:
#!/bin/bash
cd Documents/node_bot/
node fog1.js
If you want a node application to run a particular piece of code at a particular time you can run a setTimeout() recursive "loop" that checks the time every few milliseconds. If the specific time hasn't passed, the setTimeout() callback calls itself and the process starts over. However, if the time is passed, execute a specific code block and stop the recursion loop.
const triggerTime = new Date(2019, 05, 05, 02, 30, 0, 0)
function otherCodeToRun() {
// do something...
}
function wait() {
setTimeout(function() {
const currentTime = new Date()
if (currentTime >= triggerTime) {
otherCodeToRun() // not calling wait ends the recursive loop
} else {
wait() // recursively call wait after the timeout completes
}
}, 1000) // wait 1 second
}
Theoretically, that otherCodeToRun() function could call another node process to run your other file, or it could load your other file as a module and run it that way.
Also worth noting is that you could perform this check inside a while loop, however, the application will block completely, meaning it will appear unresponsive and can take up a lot of CPU cycles. The setTimeout approach gives your application a chance to yield to other processes, allowing you to log output to the console, say, if you want to display a countdown.
It should probably look more like this (absolute paths just in case):
20 14 2 5 * cd /path/to/Documents/node_bot && /path/to/node fog1.js
This runs on May 2 at 14:20
The Detox test framework, according to the documentation TroubleShooting Synchronization mentions that the test framework will wait and only perform your next test statement when the app is "Idle".
The problem I have right now is that my app never goes idle because there's some timeout that's continuously firing. It could be in my code or third-party code.
Here's an example of the output:
As you can see something is creating a new timer every few milliseconds. What'd I'd like to do is track down which one, I can see the ids but don't know a good way to try and track down exactly where this (setTimeout) id is coming from.
I thought of wrapping the setTimeout function, but not sure what's the best way to proceed with that.
I could eliminate or at least wrap setTimout in my own code, that way, at least determining it's a third-party lib (which still doesn't help solve the problem).
You could track down setTimeouts easily with:
// DEV mode only!
function failOnTimeout(func) {
const setTimeout = f => {
throw new Error(`Executing timeout \n ${f.toString()} \n`);
};
// A small trick to change scope:
eval("(" + func.toString() + ")()");
}
So you can do:
failOnTimeout(someMysteriousFunction);
And will give you stack traces of the first timeout set in that function (synchronously). You can then comment that out and search for the next one.
But instead of trackig down all timeouts, a quick solution could be to just throw an uncatched error to end the process.
I have to run some tests agains a live site.
I have to pretty much just make tasks to wait on a website to time out (15 minutes), then run another task, once that has passed.
the longest i got it to wait is 26.6 seconds (26600 ms) on firefox, and about 30 on chrome.
I get the following error :
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
so basically i need adjust the specified timeout from jasmine to run this:
browser.get('www.page.com');
browser.sleep(900000);
browser.doSomethingElse();
This is a jasmine timeout happening in your case. You need to tell Jasmine that it's okay it takes time. You can set the timeout globally in jasmineNodeOpts in your config:
jasmineNodeOpts: {
defaultTimeoutInterval: 200000,
}
Or, you can also set it on a spec level (example here).
beforeEach(function(){
browser.waitForAngular();
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
});
This is basically a follow-up to Remove timeout for single jasmine spec github issue.
The question:
Is it possible to make a single test never timeout?
The problem:
It is possible to set a timeout value globally via DEFAULT_TIMEOUT_INTERVAL or for every describe with beforeEach/afterEach or on a single it() block:
it('Has a custom timeout', function() {
expect(true).toBeTruthy();
}, value in msec)
I'm interested in having a single spec never timeout. I've tried to follow the advice proposed in the mentioned github issue and use Infinity:
it('Has a custom timeout', function() {
expect(true).toBeTruthy();
}, Infinity)
but, I've got the following error immediately after the tests got into the it() block:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL
I guess I cannot use Infinity as a timeout value, or I'm doing something wrong.
As a workaround, I can use a hardcoded large number instead, but I'd like to avoid that.
Jasmine internally uses setTimeout to wait for specs to finish for a defined period of time.
According to this Q/A - Why does setTimeout() "break" for large millisecond delay values?:
setTimeout using a 32 bit int to store the delay
...
Timeout values too big to fit into a signed 32-bit integer may cause
overflow in FF, Safari, and Chrome, resulting in the timeout being
scheduled immediately. It makes more sense simply not to schedule
these timeouts, since 24.8 days is beyond a reasonable expectation for
the browser to stay open.
As soon as Infinity is greater than any other number the overflow occurs.
The max safe integer in this case is 231-1 = 2147483647. This value is finite, so the test won't actually run infinitely long, but as said I think 24.8 days is long enough.
You can define a constant to store this value:
jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;
var MAX_SAFE_TIMEOUT = Math.pow(2, 31) - 1;
describe('suite', function () {
it('should work infinitely long', function (done) {
setTimeout(function () {
expect(true).toBe(true);
done();
}, 3000)
}, MAX_SAFE_TIMEOUT);
});
See working sample here
In a modern web browser, suppose I do a setTimeout for 10 minutes (at 12:00), and 5 minutes later put the computer to sleep, what should happen when the system wakes up again? What happens if it wakes up before the 10 minutes are up (at 12:09) or much later (at 16:00)?
The reason I'm asking is because I'd like to have a new authentication token requested every 10 minutes, and I'm not sure if the browser will do the right thing and immediately request a new token if it wakes up after a long time.
Clarifications: I don't wan't to use cookies - I'm trying to build a web service here; and yes, the server will reject old and invalid tokens.
As far as I've tested, it just stops and resumes after the computer wakes up. When the computer awakes the setInterval/setTimeout is unaware that any time passed.
I don't think you should rely on the accuracy of setTimeout/Interval for time critical stuff. For google chrome I discovered recently that any timeout/interval (that is shorter than 1s) will be slowed down to once a second if the tab where it's activated looses focus.
Apart from that the accuracy of timeouts/intervals is dependent on other functions running etc. In short: it's not very accurate.
So using interval and timeouts, checking the time against a starttime within the function started by it would give you better accuracy. Now if you start at 12:00, the computer goes to sleep and wakes up at 16:13 or so, checking 16:13 against 12:00 you are certain you have to renew the token. An example of using time comparison can be found here
Compare current datetime against datetime when the page was loaded, like so:
//Force refresh after x minutes.
var initialTime = new Date();
var checkSessionTimeout = function () {
var minutes = Math.abs((initialTime - new Date()) / 1000 / 60);
if (minutes > 20) {
setInterval(function () { location.href = 'Audit.aspx' }, 5000)
}
};
setInterval(checkSessionTimeout, 1000);
Here is my code :
<!doctype html>
<html>
<body>
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 120000)"/>
</body>
<script>
</script>
</html>
I have taken three scenarios that might answer the question.
Scenario 1: At 00 Seconds click on 'Start Timer' button . At 25 seconds computer falls asleep.
At 1min 40 seconds wake up computer.
At 2mins Alert is displayed.
Scenario 2 : At 00 Seconds click on 'Start Timer' button . At 26 seconds computer falls asleep.
At 3 mins, I wakeup the computer. The Alert is displayed.
Scenario 3 : This one is truly astounding.
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 600000)"/>
At 00 Seconds I click on 'Start Timer' button.
At around 1min 30 seconds the computer is on hibernate mode (my pc takes a minute to initiate hibernate)
At 8 mins I turn the laptop on.
At 10 mins exactly, the alert pops up.
PS: This is my first ever comment on Stack Exchange. I prefer to execute code and view results rather than infer from theory.
The behavior is based on both the browser and the operating system. The OS handle sleep and individual apps often don't account for it.
What will most likely happen is that the OS will come back up with the same time remaining on the timer as when it was shut down. The other possibility is that it won't fire at all.
If it is really a concern, you will probably want to be better safe than sorry and store a time stamp of when the token was initialized and use setInterval to check it periodically (say twice a minute).
However, security should not be just a client side thing. Make sure that your server throws an error if an old / invalid token is used and that the Ajax behaves appropriately in response.
[edit]
I agree with the other post that it might fire immediately on the next tick. Resig's blog post is very good.
Behaviour of JavaScript timers (setTimeout) in several scenarios.
When the thread is free and the timeout fires: The timer is fired immediately after the timeout. It might have certain imprecision of about 0-5 ms (typical scenario).
When the thread is super busy (huge loop) long enough to pass the timer timeout: The timer will be executed immediately after the thread is freed.
When there is an alert: Same behaviour as 2.
When the thread is paused because our laptop went to sleep: I have seen several things. But most common is total inaccuracy and ignore of the time spent during sleeping.
Since timers in JavaScript are based on CPU ticks, and the CPU is sleeping, then the timer is completely paused and resumed as 'since nothing would have happen'.
Based on Ben's answer, I created the following util. You can tweak the sampling duration, however I use it just like this for token refreshing:
const absoluteSetInterval = (handler, timeout) => {
let baseTime = Date.now();
const callHandler = () => {
if (Date.now() - baseTime > timeout) {
baseTime = Date.now();
handler();
}
};
return window.setInterval(callHandler, 1000);
};
const absoluteClearInterval = (handle) => window.clearInterval(handle);
In John Resig's blog the timers are said to be using "wall clock". I believe that the events will fire immediately after the machine is resumed because setTimeout() doesn't guarantee an execution is a specific point in time but as soon as possible after the specified interval. However, I haven't checked it myself.