I have an chart built by d3 and which appears with transitions and I need to test chart when all transitions have ended. I use jasmine for unit-testing. How to do it?
I find method d3.timer.flush(), but it skips only first frame, but I want to skip all animations and see an final result right now and make some assertions on it.
You can execute transitions synchronously directly to their final state with one call to D3's timer flush if you mock out its timestamp determination during the flush like so:
An alternative to mocking out transitions is executing them synchronously directly to their final state.
With D3.js v4, do:
function flushAllD3Transitions() {
var now = performance.now;
performance.now = function() { return Infinity; };
d3.timerFlush();
performance.now = now;
}
With D3.js v3 and previous, do:
function flushAllD3Transitions() {
var now = Date.now;
Date.now = function() { return Infinity; };
d3.timer.flush();
Date.now = now;
}
Mocking the transition altogether (to avoid the calculation overhead) yielded mixed results for me, for example if your final state is created with an attrTween, it needs to be executed.
See also our discussion in d3 issue 1789 and SO 14443724.
Related
How do I make an action occur with a delay, but after a timeout?
The setTimeout() function doesn’t work in Decentraland scenes, so is there an alternative?
For example, I want an entity to wait 300 milliseconds after it’s clicked before I remove it from the engine.
To implement this you’ll have to create:
A custom component to keep track of time
A component group to keep track of all the entities with a delay in the scene
A system that updates the timers con all these
components on each frame.
It sounds rather complicated, but once you created one delay, implementing another delay only takes one line.
The component:
#Component("timerDelay")
export class Delay implements ITimerComponent{
elapsedTime: number;
targetTime: number;
onTargetTimeReached: (ownerEntity: IEntity) => void;
private onTimeReachedCallback?: ()=> void
/**
* #param millisecs amount of time in milliseconds
* #param onTimeReachedCallback callback for when time is reached
*/
constructor(millisecs: number, onTimeReachedCallback?: ()=> void){
this.elapsedTime = 0
this.targetTime = millisecs / 1000
this.onTimeReachedCallback = onTimeReachedCallback
this.onTargetTimeReached = (entity)=>{
if (this.onTimeReachedCallback) this.onTimeReachedCallback()
entity.removeComponent(this)
}
}
}
The component group:
export const delayedEntities = engine.getComponentGroup(Delay)
The system:
// define system
class TimerSystem implements ISystem {
update(dt: number){
for (let entity of delayedEntities.entities) {
let timerComponent = entity.getComponent(component)
timerComponent.elapsedTime += dt
if (timerComponent.elapsedTime >= timerComponent.targetTime){
timerComponent.onTargetTimeReached(entity)
}
})
}
}
// instance system
engine.addSystem(new TimerSystem())
Once all these parts are in place, you can simply do the following to delay an execution in your scene:
const myEntity = new Entity()
myEntity.addComponent(new Delay(1000, () => {
log("time ran out")
}))
engine.addEntity(myEntity)
A few years late, but the OP's selected answer is kind of deprecated because you can accomplish a delay doing:
import { Delay } from "node_modules/decentraland-ecs-utils/timer/component/delay"
const ent = new Entity
ent.addComponent(new Delay(3 * 1000, () => {
// this code will run when time is up
}))
Read the docs.
Use the utils.Delay() function in the utils library.
This function just takes the delay time in milliseconds, and the function you want to execute.
Here's the full documentation, explaining how to add the library + how to use this function, including example code:
https://www.npmjs.com/package/decentraland-ecs-utils
Man, this firebase unit testing is really kicking my butt.
I've gone through the documentation and read through the examples that they provide, and have gotten some of my more basic Firebase functions unit tested, but I keep running into problems where I'm not sure how to verify that the transactionUpdated function passed along to the refs .transaction is correctly updating the current object.
My struggle is probably best illustrated with their child-count sample code and a poor attempt I made at writing a unit test for it.
Let's say my function that I want to unit test does the following (taken straight from that above link):
// count.js
exports.countlikechange = functions.database.ref('/posts/{postid}/likes/{likeid}').onWrite(event => {
const collectionRef = event.data.ref.parent;
const countRef = collectionRef.parent.child('likes_count');
// ANNOTATION: I want to verify the `current` value is incremented
return countRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
}
else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 0) - 1;
}
}).then(() => {
console.log('Counter updated.');
});
});
Unit Test Code:
const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
const assert = chai.assert;
const sinon = require('sinon');
describe('Cloud Functions', () => {
let myFunctions, functions;
before(() => {
functions = require('firebase-functions');
myFunctions = require('../count.js');
});
describe('countlikechange', () => {
it('should increase /posts/{postid}/likes/likes_count', () => {
const event = {
// DeltaSnapshot(app: firebase.app.App, adminApp: firebase.app.App, data: any, delta: any, path?: string);
data: new functions.database.DeltaSnapshot(null, null, null, true)
}
const startingValue = 11
const expectedValue = 12
// Below code is misunderstood piece. How do I pass along `startingValue` to the callback param of transaction
// in the `countlikechange` function, and spy on the return value to assert that it is equal to `expectedValue`?
// `yield` is almost definitely not the right thing to do, but I'm not quite sure where to go.
// How can I go about "spying" on the result of a stub,
// since the stub replaces the original function?
// I suspect that `sinon.spy()` has something to do with the answer, but when I try to pass along `sinon.spy()` as the yields arg, i get errors and the `spy.firstCall` is always null.
const transactionStub = sinon.stub().yields(startingValue).returns(Promise.resolve(true))
const childStub = sinon.stub().withArgs('likes_count').returns({
transaction: transactionStub
})
const refStub = sinon.stub().returns({ parent: { child: childStub }})
Object.defineProperty(event.data, 'ref', { get: refStub })
assert.eventually.equals(myFunctions.countlikechange(event), true)
})
})
})
I annotated the source code above with my question, but I'll reiterate it here.
How can I verify that the transactionUpdate callback, passed to the transaction stub, will take my startingValue and mutate it to expectedValue and then allow me to observe that change and assert that it happened.
This is probably a very simple problem with an obvious solution, but I'm very new to testing JS code where everything has to be stubbed, so it's a bit of a learning curve... Any help is appreciated.
I agree that unit testing in the Firebase ecosystem isn't as easy as we'd like it to be. The team is aware of it, and we're working to make things better! Fortunately, there are some good ways forward for you right now!
I suggest taking a look at this Cloud Functions demo that we've just published. In that example we use TypeScript, but this'll all work in JavaScript too.
In the src directory you'll notice we've split out the logic into three files: index.ts has the entry-logic, saythat.ts has our main business-logic, and db.ts is a thin abstraction layer around the Firebase Realtime Database. We unit-test only saythat.ts; we've intentionally kept index.ts and db.ts really simple.
In the spec directory we have the unit tests; take a look at index.spec.ts. The trick that you're looking for: we use mock-require to mock out the entire src/db.ts file and replace it with spec/fake-db.ts. Instead of writing to the real database, we now store our performed operations in-memory, where our unit test can check that they look correct. A concrete example is our score field, which is updated in a transaction. By mocking the database, our unit test to check that that's done correctly is a single line of code.
I hope that helps you do your testing!
I've hit a bit of an interesting road block in my attempt at writing unit tests for some middleware as I can't seem to come up with a feasible means to fake two concurrent connections for a generator function which is a piece of koa middleware.
I have a constructor function that takes some setup options and returns a generator. This generator has access to some variables via closure which increment per request and decrement when the complete. Here is a subset of the code to give you an idea of what i'm trying to accomplish.
module.exports = function (options = {}) {
let connections = 0;
let {
max = 100
...
} = options;
return function *() {
connections++
...
if (connections > max) {
connections--;
// callback here
}
...
}
}
In simple terms I want to be able to keep track of multiple simultaneous "connections" in which I fire a callback when a max number of requests have been met. However, in my test i get back a single instance of this generator and can only call it once mimicking a single request, thus i can never meet the connections > max conditional
it("Should trigger callback when max connections reached", () => {
const gen = middleware({
max: 1,
onMax: function (current, max) {
this.maxReached = true;
}
}).call(context);
gen.next();
expect(context.maxReached).to.be.true;
});
Sometimes you just need a good night sleep to dream your answer. This was simply a matter of calling the same generator with two different contexts that represented two different requests and store a value to tests against on the latter. The counter would still increment because I never returned up the middleware chain (response) in order to decrement. It's more of a fake concurrency.
const middleware = limiter({
max: 1,
onMax: function (current, max) {
this.maxReached = true;
}
});
middleware.call(reqContext).next();
middleware.call(secondReqContext).next();
expect(secondReqContext.maxReached).to.be.true;
I'm trying to use Google Visualizations from Scala.js. I generated the type definitions using TS importer and the relevant portion it generated is:
#js.native
trait ColumnChartOptions extends js.Object {
var aggregationTarget: String = js.native
var animation: TransitionAnimation = js.native
var annotations: ChartAnnotations = js.native
// ... more
}
#js.native
trait TransitionAnimation extends js.Object {
var duration: Double = js.native
var easing: String = js.native
var startup: Boolean = js.native
}
Now, I'm trying to figure out how to actually use this and came up with:
val options = js.Dynamic.literal.asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal.asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
options.animation.duration = 2000
options.title = "Test Chart"
options.width = 400
options.height = 300
This works if I don't set the animation settings, but fails with the chart showing "Maximum call stack size exceeded" if I do.
I debugged, and found the following:
So animation contains a reference to itself, but I don't feel like this should happen based on the code above.
Ideas how to fix it?
Any other suggestions on how to best use the generated types to provide a type-safe way of creating the JavaScript objects which Google Visualizations expects? I tried new ColumnChartOptions {} which looks cleaner than js.Dynamic but that failed with "A Scala.js-defined JS class cannot directly extend a native JS trait."
P.S. I'd like to note that
options.animation = js.Dynamic.literal(
easing = "inAndOut",
startup = true,
duration = 2000
).asInstanceOf[TransitionAnimation]
actually works, but isn't type-safe (a mis-spelling of duration to durration won't be caught).
Your code lacks () when calling literal(), so the fix would be:
val options = js.Dynamic.literal().asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal().asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
In Scala (and therefore in Scala.js), the presence or absence of () is sometimes meaningful. literal is the singleton object literal, whereas literal() calls the method apply() of said object.
I'm using Rhino Mocks to try to verify that when I call a certain method, that the method in turn will properly group items and then call another method.
Something like this:
//Arrange
var bucketsOfFun = new BucketGame();
var balls = new List<IBall>
{
new Ball { Color = Color.Red },
new Ball { Color = Color.Blue },
new Ball { Color = Color.Yellow },
new Ball { Color = Color.Orange },
new Ball { Color = Color.Orange }
};
//Act
bucketsOfFun.HaveFunWithBucketsAndBalls(balls);
//Assert ???
Here is where the trouble begins for me. My method is doing something like this:
public void HaveFunWithBucketsAndBalls(IList<IBall> balls)
{
//group all the balls together according to color
var blueBalls = GetBlueBalls(balls);
var redBalls = GetRedBalls(balls);
// you get the idea
HaveFunWithABucketOfBalls(blueBalls);
HaveFunWithABucketOfBalls(redBalls);
// etc etc with all the different colors
}
public void HaveFunWithABucketOfBalls(IList<IBall> colorSpecificBalls)
{
//doing some stuff here that i don't care about
//for the test i'm writing right now
}
What I want to assert is that each time I call HaveFunWithABucketOfBalls that I'm calling it with a group of 1 red ball, then 1 blue ball, then 1 yellow ball, then 2 orange balls.
If I can assert that behavior then I can verify that the method is doing what I want it to do, which is grouping the balls properly.
Any ideas of what the best testing pattern for this would be?
One way to test this is to break out the responsibility of working with a colour-specific balls to a dependency, say, IBucketHandler:
//Arrange
var bucketHandler = MockRepository.GenerateStub<IBuckerHandler>();
var bucketsOfFun = new BucketGame(bucketHandler);
...
//Assert
bucketHandler.AssertWasCalled(x => x.HaveFunWithABucketOfBalls(redBalls));
bucketHandler.AssertWasCalled(x => x.HaveFunWithABucketOfBalls(greenBalls));
This test is then checking your BucketGame correctly calls HaveFunWithABucketOfBalls on the mocked object. This may still give you trouble in specifying what each argument should be. You can in turn make this easier to test (at the expense of introducing more abstraction) by pushing the responsibility for sorting the balls to a new dependency. You'd then end up with something like this:
//Arrange
var balls = new List<IBall>(); //Can really be anything, we just need the object reference
var greenBalls = new List<IBall>();
var redBalls = new List<IBall>();
var sortedBalls = new [] { greenBalls, redBalls };
var bucketHandler = MockRepository.GenerateStub<IBucketHandler>();
var ballSorter = MockRepository.GenerateStub<IBallSorter>();
ballSorter.Stub(x => x.Sort(balls)).Return(sortedBalls);
var bucketsOfFun = new BucketGame(bucketHandler, ballSorter);
//Act
bucketsOfFun.HaveFunWithBucketsAndBalls(balls);
//Assert
bucketHandler.AssertWasCalled(x => x.HaveFunWithABucketOfBalls(greenBalls));
bucketHandler.AssertWasCalled(x => x.HaveFunWithABucketOfBalls(redBalls));
And to pass this test, in BucketGame:
public BucketGame(IBucketHandler bucketHandler, IBallSorter ballSorter)
{
this.bucketHandler = bucketHandler;
this.ballSorter = ballSorter;
}
public void HaveFunWithBucketsAndBalls(IList<IBall> balls)
{
//group all the balls together according to color
var sortedBalls = ballSorter.Sort(balls);
foreach (var groupOfBalls in sortedBalls)
{
bucketHandler.HaveFunWithABucketOfBalls(groupOfBalls);
}
}
This tests the BucketGame logic. You'll now want to write unit tests for an IBallSorter implementation to check that it sorts the balls by colour as you require. Those tests probably won't need any mocking, you'll simply be able to throw data in and assert that the data you get back is what you expect.
the first thing you need to sort out in any test is what exactly your Subject Under Test is. that might sound gratuitous but I know from my own experiences that this can be confusing when you are learning interaction testing.
the reason I am guessing this is part of the problem is that you have an IBall object, but you want to asserts calls being made on a method that doesn't appear to be part of an interface. As you know, Rhino does it's magic by overriding something virtual, like an interface; so if you want to use to Rhino to do this you have to give it an interface. Assuming that is the case, maybe
interface IBucketGame{
void HaveFunWithBucketsAndBalls(IList<IBall> balls)
void HaveFunWithSpecificBalls(IList<IBall> balls)
}
Now you can set up an interaction test:
[Test]
public void HaveFunWithBucket_IfMoreThanOneColor_CallsHaveFunWithSpecificBallsForSpecificColor()
{
//Arrange
var bucketsOfFun = MockRepository.GenerateMock<IBucketGame>();
IBall expColor_1 = new Ball(Color.Red);
IBall expColor_2 = new Ball(Color.Green);
IBall expColor_3 = new Ball(Color.Red);
var startlist = new List<IBall>{expColor_1, expColor_2, expColor_3};
var onlyRedBalls = new List<IBall>{expColor_1, expColor_3};
var onlyGreenBalls = new List<IBall>{expColor_2};
//Act
bucketsOfFun.HaveFunWithBucketsAndBalls(balls);
//Assert
bucketsOfFun.AssertWasCalled(x=>x.HaveFunSpecificBalls(Arg<IEnumerable<IBall>>.List.Equal(onlyRedBalls)));
bucketsOfFun.AssertWasCalled(x=>x.HaveFunSpecificBalls(Arg<IEnumerable<IBall>>.List.Equal(onlyGreenBalls)));
}
HTH,
Berryl