confusion about velocity's beforeEach setUp function in meteor - javascript

I'm trying to implement testing on my meteor application using velocity [1] and jasmine [2].
I defined a collection called 'object' (collections/object.js):
Objects = new Meteor.Collection('objects');
I implemented a set up function (tests/jasmine/server/unit/ObjectSpec.js):
describe('Objects', function () {
'use strict';
// set up
beforeEach(function () {
// 1 - backup all data
MeteorStubs.install();
// 2 - delete current 'Objects'-items
Objects.remove({});
// 3 - add test data
Objects.insert({
someProperty: 'data1'
});
});
then I do run the actual tests (same file):
// actual tests
it("should delete a specific object", function () {
var selector = {someProperty: 'data1'};
var selectedObject = Objects.findOne(selector);
// will return 'Expected undefined not to be undefined.'
expect(selectedObject).not.toBe(undefined);
Meteor.call('deleteObject', selectedObject, function(error, id) {
if (error)
return alert(error.reason);
});
expect(Objects.findOne(selector)).toBe(undefined);
});
after, I restore the old application state in the tear down (same file):
// tear down
afterEach(function () {
Objects.remove({});
MeteorStubs.uninstall();
});
Now, when executing the test, velocity throws me:
Expected undefined not to be undefined.
I wonder, if the data in the 'beforeEach'-Function actually will be inserted and accessible in the actual testing function? Also, I tried using console.log() in the test functions, to show the current data, but it won't be shown in the browser console. Why?
[1] https://atmospherejs.com/velocity/html-reporter
[2] https://atmospherejs.com/sanjo/jasmine

Related

Error in web worker using web assembly

I would like to use WebAssembly within a web worker.
From my main application, I launch it like this:
let w = new Worker('test.js');
w.onmessage = (event) => { console.log(event); };
w.onerror = (event) => { console.error(event); };
w.postMessage({ message: "Hello World" });
Then, I created a file test.js as follows:
self.Module = {
locateFile: function (s) {
console.log(s);
return s;
}
};
self.importScripts("main.js");
// note: `main.js` is the JavaScript glue file created by emcc
self.onmessage = function(messageEvent) {
console.log(messageEvent); // works!
console.log(self.Module); // works!
console.log(self.Module.ccall("test")); // crashes!
}
I get an error: Uncaught TypeError: Cannot read property 'apply' of undefined. I don't understand why self.Module is undefined, how is that possible?
I have the feeling there is something about the scope of the web worker and WebAssembly that does not work well together.
Thanks for your input!
The problem is that console.log() does not reveal the true state of the object at execution time. Further digging revealed that in fact the object Module was not ready yet.
I cite from: https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html
How can I tell when the page is fully loaded and it is safe to call compiled functions?
Calling a compiled function before a page has fully loaded can result
in an error, if the function relies on files that may not be present
[...]
Another option is to define an
onRuntimeInitialized function:
Module['onRuntimeInitialized'] = function() { ... };
That method will be called when the runtime is ready and it is ok for you to call compiled code.
Adjusting my test.js (worker) file fixes the issue:
self.Module = {
locateFile: function (s) {
console.log(s);
return s;
}
// Add this function
onRuntimeInitialized: function() {
test();
}
};
self.importScripts("main.js");
// note: `main.js` is the JavaScript glue file created by emcc
self.data = {};
// to pass data from the main JS file
self.onmessage = function(messageEvent) {
console.log(messageEvent); // works!
self.data = messageEvent; // save the data
}
// gets executed when everything is ready.
self.test = function() {
// we may safely use self.data and self.Module now!
console.log(self.Module.ccall("test")); // works!
}

TypeError: undefined is not an object when unit testing with jasmine

I'm trying to write a unit test for a function and I'm getting an error. I'm also unsure how to test other parts of the function correctly.
private dictionaryMap (loggedIn, response) {
const translations = this.convertToArrays(response.data.translations);
this.configureMomentLocale(language);
if (!loggedIn) {
this.cachePublicDictionary(translations);
}
// not testing this part
this.dictionary = new Dictionary({
translationMap: Object.assign({}, this.getPublicDictionaryFromCache() || {}, translations),
});
return this.rx.Observable.of(this.dictionary);
}
And my unit test so far looks like this:
describe('dictionaryMap', () => {
it('calls configureMomentLocale()', () => {
const foo = {
'foo':'bar',
};
spyOn(service, 'configureMomentLocale');
service.dictionaryMap({}, false);
expect(service.configureMomentLocale).toHaveBeenCalled();
});
});
And when I run this test I get this error:
TypeError: undefined is not an object (evaluating 'response.data.translationMap')
Do I need to mock response.data.translations or assign the json structure? (translationMap: {'email': 'email', 'forgotPassword': 'Forgot password?'})
Also, I'm not sure how to properly test the other parts of the function, like the if statement or returning the observable. I am new to unit testing.
Your method dictionaryMap accepts 2 parameters - 1st is loggedIn (presumably boolean) and the 2nd one is response. On the first line of that method (before calling configureMomentLocale) you have a line const translations = this.convertToArrays(response.data.translations); which expects the response variable to have a property named data.
In your test, you have 2 errors on the line service.dictionaryMap({}, false);:
You're setting the arguments in reverse order - you should put the boolean argument first and the object one second
The object doesn't have a property named data
The line should be corrected to be something similar to service.dictionaryMap(false, { data: {} });. You might even need to define translations property for data object - it really depends on what this.convertToArrays function does and how it handles undefined values.

How to reactively call a Meteor method referenced by a reactive variable?

I am trying to invoke a Meteor method not with a hard-coded string but with a Session variable which contains its name. It works once but does not re-run the method when the Session value is changed via Session.set.
Server code:
Meteor.methods({
hello: function () {
console.log("hello");
},
hi: function () {
console.log("hi");
}
});
Client code:
Session.set('say', 'hi');
Meteor.call(Session.get('say')); // console prints hi
Session.set('say', 'hello'); // console is not printing, expected hello
How can I get the "new" method to be called after the Session value is changed, reactively?
You need a reactive context to achieve this kind of home-made reactivity.
You can achieve this simply with Tracker.autorun:
Session.set('say', 'hi');
Tracker.autorun(function callSayMethod() {
Meteor.call(
Session.get('say')
);
});
Meteor.setTimeout(
() => Session.set('say', 'hello'),
2000
);
Spacebars template helpers use that kind of context to achieve reactivity in templates.
Note that you don't need Session here. A simple ReactiveVar would be enough:
const say = new ReactiveVar('hi');
Tracker.autorun(function callSayMethod() {
Meteor.call(
say.get()
);
});
Meteor.setTimeout(
() => say.set('hello'),
2000
);

First async unit test with Mocha and Sinonjs

I m actually using a micro framework created by my society in which we use Mongoose.
To manage the mongoose object, we created a modelfactory, that returns us a model corresponding to the mongoose name object.
Actually, I m working on an authentication service in which I inject this modelfactory.
I need to unit test it with mocha and sinonjs, but I m a bit lost...
This is my authentication Service method that I want to test :
class AuthenticationService extends Service
constructor: (modelFactory)->
super(modelFactory)
#authorizedClientIds = [
"123456"
"toto"
]
#OAuthAccessTokensModel = #modelFactory.getSchema('OAuthAccessTokens')
#OAuthClientsModel = #modelFactory.getSchema('OAuthClients')
#OAuthUsersModel = #modelFactory.getSchema('OAuthUsers')
#OAuthRefreshTokensModel = #modelFactory.getSchema('OAuthRefreshTokens')
## Get an access token from the bearer token ##
getAccessToken: (bearerToken, callback)->
#OAuthAccessTokensModel.findOne({accessToken: bearerToken}, callback)
module.exports = AuthenticationService
I want to test the getAccessToken method, but I have clearly no idea how to make it work...
I've tried to make something like :
describe("Authentication Service", function () {
var service;
before(function () {
ModelFactory = use('/app/core/config/database/ModelFactory');
var mock = sinon.mock(ModelFactory.getFactoryInstance([]));
mock.expects("getSchema").withArgs("user").return({name:'user',getName:function(){}});
service = new AuthenticationService(mock);
});
describe("getAccessToken", function () {
it('should return-1 when the value is not present', function () {
var proxy = once(service.getAccessToken());
mock.verify();
});
});
});
How should I do to test it correctly ?
EDIT :
I've tried something, but it seems weird to test because I propose the result to compare, but the result expected too.. So I could never fail the test :x...
describe("Authentication Service", function () {
var service;
before(function () {
ModelFactory = use('/app/core/config/database/ModelFactory');
var factory = new ModelFactory([]);
sinon.stub(factory, "getSchema").returns({findOne: sinon.stub().returns()});
service = new AuthenticationService(factory);
});
describe("getAccessToken", function () {
it('Check if the access token correspond to a database entry', function () {
stubResult = {token: '123456'};
service.getAccessToken = sinon.stub().withArgs('1234').returns(undefined);
assert.equal(service.getAccessToken(), undefined);
});
});
});
Some help ?
Thanks for advance
The Unit test should test something that is not mocked/stubbed.
When you have a difficult method handleUnknownToken() this function can call your Authentication Service. The assert() should verify that the handling of the 'undefined' works as expected.
In other words: When you want to unit test f(x) = g()+h() +j(); you can test the correct implementation of g() by stubbing h() and j(), test h() by stubbing g() and j() and test j() by stubbing g() and h().
EDIT: The explanation above is abstract, since I do not know Mongoose/Mocha/Sinonjs. Beneath I'll try to focus on the case described.
When your service getAccessToken() is completely stubbed, the next tests
will succeed when your stub definition is correct:
testUnknown() {
constant UKNOWN_ITEM='1234';
assert.equal(service.getAccessToken(UNKNOWN_ITEM), undefined);
}
testTimeout() {
constant DIFFICULT_ITEM='1235';
assert.equal(service.getAccessToken(DIFFICULT_ITEM), STATUS_TIMEOUT);
}
testRevoked() {
constant REVOKED_ITEM='1236';
assert.equal(service.getAccessToken(REVOKED_ITEM), STATUS_DENIED);
}
testActive() {
constant ACTIVE_ITEM='1237';
assert.equal(service.getAccessToken(ACTIVE_ITEM), STATUS_OK);
}
Your test must include some logic you don't stub.
Waht is the code around calling getAccessToken()? Something like a function
isTokenOK(), that will look at the status and retry 5 times after a timeout?
With the stubs implemented for the above test you can test the boolean function isTokenOK() with
testUnknown() {
assertFalse(isTokenOK(UNKNOWN_ITEM));
}
testTimeout() {
assertFalse(isTokenOK(DIFFICULT_ITEM));
}
testRevoked() {
assertFalse(isTokenOK(REVOKED_ITEM));
}
testActive() {
assertTrue(isTokenOK(ACTIVE_ITEM));
}
And now, when somebody changes the implementation of isTokenOK(), your unit test can fail. When the unit test is failing, you must look who is right.
Maybe a token that has been revoked can be used for authentication the first 10 minutes after revocation and isTokenOK(REVOKED_ITEM) should be true.
Oh well, than you must add a new test for REVOKED_ITEM_YESTERDAY.

How to use qunit in a backbone app

I'm currently working on an app that is built from Backbone.js, with Require.js to load dependencies. I had hoped to be able to load QUnit and have a page where the user can simply load the page and it will dynamically run unit tests. However, I've hit a snag. Whenever I load the page, the tests work, but if I navigate away from the page and then come back, QUnit breaks with the following error:
Uncaught Error: pushFailure() assertion outside test context,
Below is the code that I am currently working with. My real question is this: With my current Backbone.js layout, is it feasible to use QUnit in the way I want, or should I scrap this feature?
When the page loads, the parent view service_test.view.js is rendered:
define(['backbone', 'hgn', 'statemachine_test_view'],
function (Backbone, hgn, StateMachineTest) {
var DynamicTest = Backbone.View.extend({
// This is the main element of the application, it is what is cleared and populated for each page
el: $(".overwatch_container"),
// Build the Statemachine test view (statemachine_test.view.js)
statemachine_view: new StateMachineTest(),
render: function (data) {
// Empty out anything that's in the container already
this.$el.empty();
// Contain the 'this' reference, so it can be used throughout
var that = this;
// Pull in and populate the hogan template for the main parent elements
require(['hgn!templates/service_test.template.hogan'], function (tmpl) {
// JSON object with all of thd page's information to pass to the templates
resultset = {
"service_type": data.service_type
};
// Render the template with the given information, and then build child views
if( that.$el.html( tmpl.render( resultset ) ) )
{
// Build the child view
that.statemachine_view.render();
}
});
},
close: function () {
$(this.$el).empty();
return this;
}
});
// Return the view object, so it can be utilized when this script is require'd
return DynamicTest;
});
statemachine_test.view.js is where StateMachineTest is created:
define(['backbone', 'hgn'],
function (Backbone, hgn) {
var StateMachineTest = Backbone.View.extend({
render: function (options) {
// Dynamically set the element associated with this view, as it is not instantiated when this is first included by Require.js
this.setElement( $(".test_content") );
// Contain the 'this' reference, so it can be used throughout
var that = this;
require(['hgn!templates/qunit_base.template.hogan'], function (tmpl) {
// JSON object with all of thd page's information to pass to the templates
// Render the template with the given information, and then build child views
if( that.$el.html(tmpl.render()) )
{
// Once the template has been rendered, load the qUnit test script
// 'statemachine_dynamic' = statemachine_dynamic.test.js
require(['QUnit', 'statemachine_dynamic'], function(QUnit, statemachine) {
statemachine.run();
QUnit.load();
QUnit.start(); //THIS IS THE LINE THE ERROR POINTS TO
QUnit.done( function (details) {
_.each($("#qunit-tests li").children("a"), function (child) {
$(child).attr("href", function (index, attr) {
return attr+window.location.hash;
});
});
});
});
}
});
},
});
return StateMachineTest;
});
And this is my actual test script, statemachine_dynamic.test.js:
define([], function () {
var run = function() {
module("Statemachine Testing");
test( "Test 1", function() {
var value = "hello";
equal( value, "hello", "We expect value to be hello" );
});
test( "Test 2", function() {
var value = "hello";
equal( value, "hello", "We expect value to be hello" );
});
test( "Test 3", function() {
var value = "hello";
equal( value, "hello", "We expect value to be hello" );
});
};
return {run: run};
});
Qunit.start() doesn't start the tests. start() is for async testing if you comment it out your test will probably be run aswel altough i do not know require.js

Categories