Skip to content

Commit

Permalink
Release 0.1.3 (#3)
Browse files Browse the repository at this point in the history
- inform user about the functionality being inactive on server
- client side unit tests
  • Loading branch information
Tomasz Przytuła committed Feb 4, 2018
1 parent 7bd9296 commit b0ff369
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 25 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [0.1.3] - 04.02.2018
* Inform client if the functionality was not activated on the server
* Client side unit tests

## [0.1.2] - 01.02.2018
* Remove 'lodash' dependency, replace usages using ES6
* Remove 'crypto-js' dependency, use 'crypto' instead
Expand All @@ -10,4 +14,4 @@
* Add server side tests

## [0.1.0] - 19.01.2018
* Initial release
* Initial release
40 changes: 22 additions & 18 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import { Accounts } from 'meteor/accounts-base';
import overrideAccountsLogin from './overrideLogin';
overrideAccountsLogin();

const RememberMe = {};
const updateRememberMe = 'tprzytula:rememberMe-update';

RememberMe.loginWithPassword = (user, password, callback = () => {}, rememberMe = true) => {
let flag = rememberMe;
let callbackMethod = () => {};
const flag = (typeof callback === 'boolean')
? callback
: rememberMe;

if (typeof callback === 'boolean') {
flag = callback;
} else {
callbackMethod = callback;
}
const callbackMethod = (typeof callback === 'function')
? callback
: () => {};

Meteor.loginWithPassword(user, password, (error) => {
if (!error) {
Meteor.call(updateRememberMe, flag);
Meteor.call(updateRememberMe, flag, (error) => {
if (error && error.error === 404) {
console.warn(
'Dependency meteor/tprzytula:remember-me is not active!\n',
'\nTo activate it make sure to run "RememberMe.activate()" on the server.' +
'It is required to be able to access the functionality on the client.'
)
} else if (error) {
console.error(
'meteor/tprzytula:remember-me' +
'\nCould not update remember me setting.' +
'\nError:', error
);
}
});
}
callbackMethod(error);
});
};

let loginOverridden = false;
Accounts.onLogin(() => {
/* Override meteor accounts callLoginMethod to store information that user logged before */
if (!loginOverridden) {
overrideAccountsLogin();
loginOverridden = true;
}
});

export default RememberMe;
15 changes: 14 additions & 1 deletion client/overrideLogin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Accounts } from 'meteor/accounts-base';

/**
* This function is used to override Account's function called callLoginMethod.
* We are using our custom implementation of remember me functionality where user
Expand All @@ -19,7 +21,7 @@
* Launching the app again means that it will became default again without our additions.
* Then the next successful login will override it again.
*/
export default () => {
const overrideLoginMethod = () => {
const accountsCallLoginMethod = Accounts.callLoginMethod.bind(Accounts);
Accounts.callLoginMethod = function (options = {}) {
const preparedOptions = options;
Expand All @@ -33,3 +35,14 @@ export default () => {
accountsCallLoginMethod(preparedOptions);
};
};

export default () => {
let loginOverridden = false;
Accounts.onLogin(() => {
/* Override meteor accounts callLoginMethod to store information that user logged before */
if (!loginOverridden) {
overrideLoginMethod();
loginOverridden = true;
}
});
};
10 changes: 8 additions & 2 deletions package.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package.describe({
name: 'tprzytula:remember-me',
version: '0.1.2',
version: '0.1.3',
summary: 'Extension for Meteor account-base package with the implementation of rememberMe',
git: 'https://github.com/tprzytulacc/Meteor-RememberMe',
documentation: 'README.md'
Expand All @@ -23,5 +23,11 @@ Package.onTest((api) => {
api.use('meteortesting:mocha');
api.use('tprzytula:remember-me');
api.use('practicalmeteor:chai');
api.use('practicalmeteor:sinon');
api.mainModule('test/client/index.js', 'client');
api.mainModule('test/server/index.js', 'server');
});
Npm.depends({
sinon: '4.2.2'
});

});
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rememberMe",
"version": "0.1.2",
"version": "0.1.3",
"description": "Extension for Meteor account-base package with the implementation of rememberMe",
"license": "MIT",
"author": "Tomasz Przytuła <[email protected]>",
Expand All @@ -16,6 +16,7 @@
],
"homepage": "https://github.com/tprzytulacc/Meteor-Remember-Me",
"scripts": {
"test": "meteor test-packages ./ --driver-package meteortesting:mocha"
"test": "meteor test-packages ./ --once --driver-package meteortesting:mocha",
"test-watch": "TEST_WATCH=1 meteor test-packages ./ --full-app --driver-package meteortesting:mocha"
}
}
}
10 changes: 10 additions & 0 deletions test/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const method = require('./tests/method');
const rememberMe = require('./tests/rememberMe');

/**
* Client-side test cases.
*/
describe('client', () => {
method();
rememberMe();
});
120 changes: 120 additions & 0 deletions test/client/tests/method.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const RememberMe = require('meteor/tprzytula:remember-me').default;
const rememberMeMethod = 'tprzytula:rememberMe-update';
const sinon = require('sinon');

module.exports = () => {
/**
* RememberMe.loginWithPassword is a wrapper for the Meteor's
* loginWithPassword method. It should match specific behaviour.
*/
describe('Invoking "RememberMe.loginWithPassword" method', () => {
/**
* Each time the wrapper is called it
* should also internally call the Meteor's login method.
*/
it('should call Meteor.loginWithPassword', () => {
const loginWithPassword = sinon.stub(
Meteor,
'loginWithPassword'
);

RememberMe.loginWithPassword('username', 'password');
expect(loginWithPassword).to.have.been.calledOnce;
expect(loginWithPassword).to.have.been.calledWith(
'username',
'password'
);

RememberMe.loginWithPassword('username_two', 'password_two');
expect(loginWithPassword).to.have.been.calledTwice;
expect(loginWithPassword).to.have.been.calledWith(
'username_two',
'password_two'
);

loginWithPassword.restore();
});

/**
* Updating the Remember Me status is only relevant if the login
* performed successfully. Otherwise there is no reason to send
* this request to the server.
*/
it('should not call updateRememberMe method if login failed', () => {
const loginWithPassword = sinon.stub(Meteor, 'loginWithPassword');
const call = sinon.stub(Meteor, 'call');
loginWithPassword.callsFake((user, password, callback) => {
const error = 'Invalid user';
callback(error);
});
RememberMe.loginWithPassword('username', 'password');
expect(loginWithPassword).to.have.been.calledOnce;
expect(call).to.have.callCount(0);

loginWithPassword.restore();
call.restore();
});

/**
* If the login performed successfully then method for updating
* the state of remember me should be invoked. This way server
* will be informed about requested change for this setting.
*/
it('should call updateRememberMe method if logged in successfully', () => {
const loginWithPassword = sinon.stub(
Meteor,
'loginWithPassword'
);
const call = sinon.stub(Meteor, 'call');
loginWithPassword.callsFake((user, password, callback) => {
const error = false;
callback(error);
});
RememberMe.loginWithPassword('username', 'password');
expect(loginWithPassword).to.have.been.calledOnce;
expect(loginWithPassword).to.have.been.calledWith(
'username',
'password'
);
expect(call).to.have.been.calledOnce;
expect(call).to.have.been.calledWith(rememberMeMethod);

loginWithPassword.restore();
call.restore();
});

/**
* Meteor.loginWithPassword takes a callback as a parameter.
* The callback provided to the RememberMe.loginWithPassword
* should be invoked after received response from the Meteor's
* internal login method. It should also sent the error as
* a parameter (if encountered).
*/
it('should correctly pass callback to "Meteor.loginWithPassword"', () => {
const loginWithPassword = sinon.stub(
Meteor,
'loginWithPassword'
);
const call = sinon.stub(Meteor, 'call');
const error = 'User does not exist';
loginWithPassword.callsFake((user, password, callback) => {
callback(error);
});
const obj = {};
obj.callback = (error) => error;
const callbackSpy = sinon.spy(obj, 'callback');
RememberMe.loginWithPassword('username', 'password', obj.callback);
expect(loginWithPassword).to.have.been.calledOnce;
expect(loginWithPassword).to.have.been.calledWith(
'username',
'password'
);

expect(callbackSpy).to.have.been.calledOnce;
expect(callbackSpy).to.have.been.calledWith(error);

loginWithPassword.restore();
call.restore();
});
});
};
Loading

0 comments on commit b0ff369

Please sign in to comment.