Testing with Tinytest exceptions - meteor

I am working on unit test using Tinytest in a package and I wanted to test that a method raise an exception and I can test it using test.throws().
I create a meteor project :
meteor create myapp
cd myapp
meteor add tinytest
To create a package, I do
meteor create --package test-exception
And this is my simple test
File test-exception.js
Joe = {
init: function () {
throw "an exception";
}
}
File package.js
Package.describe({
name: 'tinytest-throws',
version: '0.0.1'
});
Package.onUse(function(api) {
api.versionsFrom('1.2.0.2');
api.use('ecmascript');
api.addFiles('tinytest-throws.js');
api.export('Joe', 'server'); // create a global variable for the server side
});
Package.onTest(function(api) {
api.use('ecmascript');
api.use('tinytest');
api.use('tinytest-throws');
api.addFiles('tinytest-throws-tests.js', 'server'); // launch this test only as server
});
File test-exception-tests.js
Tinytest.add('Call a method that raise an exception', function (test) {
test.throws(
Joe.init, // That could be a way, but this fails
"This is an exception"
);
test.throws(
Joe.init(),
"This is an exception"
);
});
Does somebody know how to test that exceptions are well raised ?

Ok I get it.
First, you have to use Meteor.Error. So my Joe object becomes :
Joe = {
init: function () {
throw new Meteor.Error("This is an exception");
}
}
Now, I can catch the error using Test.throws :
test.throws(
function() {
Joe.init()
},
"n except" // a substring of the exception message
);

Related

Meteor: callLoginMethod not found error

I'm having difficulty invoking a login method, it follows
$ meteor list
Accounts-base 1.2.14 A user account system
Ecmascript 0.6.1 Compiler plugin that supports ES2015 + in all .js files
Meteor-base 1.0.4 Packages that every Meteor app needs
React 15.0.1 Everything you need to use React with Meteor.
Static-html 1.1.13 Defines static page content in .html files
/server/main.js
import { Accounts } from 'meteor/accounts-base'
Accounts.registerLoginHandler('simples', (ttt) => {
console.log(ttt);
});
/client/main.js
autenticar(){
Accounts.callLoginMethod({
methodName: 'simples',
methodArguments: [{ tipo : 'simples' }],
validateResult: function (result) {
console.log('result', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
})
}
When calling authenticar(), I get this error:
errorClass
  Details: undefined
  Error: 404
  ErrorType: "Meteor.Error"
  Message: "Method 'simples' not found [404]"
  Reason: "Method 'simples' not found"
Where is the error?
I've never used this API personally, but from a quick glance through the Meteor internals, I see a couple issues.
Accounts.registerLoginHandler only adds an additional handler to an array of built-in handlers which are called as part of the default Meteor login process.
If you are trying to plug in an additional handler into the existing process, you should call Accounts.callLoginMethod without the methodName key.
Calling Accounts.callLoginMethod with methodName will bypass the built-in handlers completely and replace them with your custom method, however this method needs to be declared separately by you with Meteor.methods, not registerLoginHandler.
So, that's probably your error -- you need to define your simples method with Meteor.methods. Also, you should check the code for the requirements of this method, see the comments in the code here:
https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_client.js
Only to complement and keep as a referral for someone else to get here. That way it's working
client.js
Accounts.callLoginMethod({
methodArguments: [{tipo: 'simples'}],
validateResult: (result) => {
console.log('success', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
});
server.js
Meteor.startup(function () {
var config = Accounts.loginServiceConfiguration.findOne({
service : 'simples'
});
if (!config) {
Accounts.loginServiceConfiguration.insert({ service: 'simples' });
}
});
Accounts.registerLoginHandler((opts) => {
if(opts.tipo === 'simples'){
return Accounts.updateOrCreateUserFromExternalService ('simples', {
id: 0 // need define something
}, {
options : 'optional'
})
}
});

Restivus authentication for Meteor methods

I'm trying to make my meteor-app for REST services available. For this I use the package "Restivus" which also works just fine. But once I'd like to run a meteor method this.userId is undefined.
Api.addRoute('addArticle', {authRequired: true}, {
post: function () {
console.log(this.userId); //<-- hwuqtFXf8aKperJ5p
try {
Meteor.call("addArticle",this.bodyParams);
} catch (e) {
return {code:500,type:e.error,reason:e.reason};
}
}
});
the method:
new ValidatedMethod({
name: 'addArticle',
....
if (!this.userId) {
throw new Meteor.Error(...); //is thrown
}
What am I doing wrong?
In Meteor methods you get the current userId by doing
Meteor.userId()
and not
this.userId
So you would need to update your code to
if(!Meteor.userId()){
throw new Meteor.Error(403, '403:Forbidden', 'You shall not pass!')
}

"Object is not a function" in a Meteor route

I just created two routes that work just fine, but I'm getting an odd error in the console that I would like to fix.
Exception in callback of async function: TypeError: object is not a function
at OnBeforeActions.loginRequired (http://localhost:3000/client/router/config.js?8cea1a53d7ab131377c2c4f91d534123cba79b70:12:20)
This error shows up every time I visit the same page.
This is my config.js file:
Router.configure({
layoutTemplate: "uMain"
});
var OnBeforeActions = {
loginRequired: function (pause) {
"use strict";
if (!Meteor.userId()) {
this.render("uLogin");
return pause();
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
except: ["uLogin"]
});
The idea is to redirected all user who are not logged in to "uLogin".
It works (or I haven't found any bugs so far).
What am I doing wrong?
You can see the line where you have the error in developers console when you click on link http://localhost:3000/client/router/config.js?8cea1a53d7ab131377c2c4f91d534123cba79b70:12:20 in your console.
Your problem is that new Iron Router does not use pause() anymore. Remove pause from your onBeforeAction.
Developers console is your good friend. Learn how to use it.

How to properly replace this.stop() with pause() on Iron Router blaze integration

When I upgrade Iron Router to blaze integration branch, I began receiving this warning:
"You called this.stop() inside a hook or your action function but you should use pause() now instead"
Chrome console --> iron-router.js:2104 --> client/route_controller.js:193 from package
The code is on client:
Router.before(mustBeSignedIn, {except: ['userSignin', 'userSignup', 'home']});
var mustBeSignedIn = function () {
if (!Meteor.user()) {
// render the home template
this.redirect('home');
// stop the rest of the before hooks and the action function
this.stop();
return false;
}
return true;
}
I tried replacing this.stop() with: pause(), Router.pause() and this.pause() but still does not work. Also I haven't found pause function on iron-router package.
How do I properly replace this.stop() with pause()?
Thanks
From what I can tell the pause function is the first parameter your before hook is getting called with. Not in the docs anywhere, but that's what I gathered from the code and it seems to work.
Here's what I use:
var subscribeAllPlanItems = function (pause) {
var planId = this.params._id;
this.subscribe('revenues', planId).wait();
this.subscribe('expenses', planId).wait();
};
var waitForSubscriptions = function (pause) {
if (this.ready()) { //all the subs have come in
//NProgress.done();
setPlan(this.params._id);
} else { //all subscriptions aren't yet ready, keep waiting
//NProgress.start();
pause();
}
};
Router.map(function () {
this.route('calendar', {
path: '/calendar/:_id',
template: 'calendar',
before: [
subscribeAllPlanItems,
waitForSubscriptions
],
});
//Other routes omitted
});
var requireLogin = function (pause) {
if (Meteor.loggingIn()) { //still logging in
pause();
}
if (!Meteor.user()) { //not logged in
this.render('signIn');
pause();
} else { //logged in, life is good
console.log("requireLogin: logged in");
}
};
//This enforces login for all pages except the below ones.
Router.before(requireLogin, {
except: ['landing', 'signUp', 'signIn', 'forgotPassword', 'resetPassword']
});
I opened an issue on Github about this. Here's the response I got:
Oops I may have not changed the redirect method yet. Just use Router.go as it will work fine now. I will change over this.redirect sometime next week or a PR is welcome. Controllers are now automatically stopped if you change routes in a hook. You can pause the current run by calling the pause method which is passed as a parameter to your hooks and action functions.

How can I use NodeJS modules in Meteor?

In a NodeJS application ,I have finished some modules,Now I want to use them in Meteor,What should I do?
For example,there is a file 'hello.js',content:
require('url');// In here,require other modules
function sayHi(name){
console.log("Hi "+ name);
}
exports.sayHi = sayHi;
How do I use 'say Hi' in meteor?
when I do this:
if (Meteor.isServer) {
Meteor.startup(function () {
var require = __meteor_bootstrap__.require;
var index = require('./hello');
hello.syaHi('Ec');})}
Errors is:
app/index.js:1
require();
^
ReferenceError: require is not defined
at app/index.js:1:1
at /home/huyinghuan/workspace/NodeJs/myMeteorJS/testrequire/.meteor/local/build/server/server.js:113:21
at Array.forEach (native)
at Function._.each._.forEach (/usr/lib/meteor/lib/node_modules/underscore/underscore.js:79:11)
at run (/home/huyinghuan/workspace/NodeJs/myMeteorJS/testrequire/.meteor/local/build/server/server.js:99:7)
I think, you have to install/copy your module into projectdir/.meteor/local/build/server/node_modules which is a link to /usr/local/meteor/lib/node_modules. I tried this with the node.js module tracer and it worked. You have to copy your files into this directory every time you updated your meteor installation.
Also, it looks like Npm.require() is the right way to require node modules now.
Update, I had to install my module into .meteor/local/build/programs/server/node_modules as well as use Npm.require.
Here's a package which makes it a lot easier to use NPM packages inside Meteor:
https://github.com/meteorhacks/npm
example usage:
if (Meteor.isClient) {
getGists = function getGists(user, callback) {
Meteor.call('getGists', user, callback);
}
}
if (Meteor.isServer) {
Meteor.methods({
'getGists': function getGists(user) {
var GithubApi = Meteor.npmRequire('github');
var github = new GithubApi({
version: "3.0.0"
});
var gists = Async.runSync(function(done) {
github.gists.getFromUser({user: 'arunoda'}, function(err, data) {
done(null, data);
});
});
return gists.result;
}
});
}

Resources