Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #609 from alepop/568-migrate-desktop-notifications…
Browse files Browse the repository at this point in the history
…-to-react

Migrate desktop notifications to react - Closes #568
  • Loading branch information
slaweet committed Aug 21, 2017
2 parents 2c3d897 + 18772c3 commit fa4c2ca
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/store/middlewares/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import metronomeMiddleware from './metronome';
import accountMiddleware from './account';
import loginMiddleware from './login';
import notificationMiddleware from './notification';

export default [
loginMiddleware,
metronomeMiddleware,
accountMiddleware,
notificationMiddleware,
];
23 changes: 23 additions & 0 deletions src/store/middlewares/notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import actionTypes from '../../constants/actions';
import Notification from '../../utils/notification';

const notificationMiddleware = (store) => {
const notify = Notification.init();
return next => (action) => {
const { account } = store.getState();
next(action);

switch (action.type) {
case actionTypes.accountUpdated: {
const amount = action.data.balance - account.balance;
if (amount > 0) {
notify.about('deposit', amount);
}
break;
}
default: break;
}
};
};

export default notificationMiddleware;
59 changes: 59 additions & 0 deletions src/store/middlewares/notification.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { expect } from 'chai';
import { spy, stub } from 'sinon';
import middleware from './notification';
import actionTypes from '../../constants/actions';
import Notification from '../../utils/notification';

describe('Notification middleware', () => {
let store;
let next;
const accountUpdatedAction = balance => ({
type: actionTypes.accountUpdated,
data: {
balance,
},
});

beforeEach(() => {
next = spy();
store = stub();
store.getState = () => ({
account: {
balance: 100,
},
});
store.dispatch = spy();
});

it('should init Notification service', () => {
const spyFn = spy(Notification, 'init');
middleware(store);
expect(spyFn).to.have.been.calledWith();
spyFn.restore();
});

it('should just pass action along for all actions', () => {
const sampleAction = {
type: 'SAMPLE_TYPE',
data: 'SAMPLE_DATA',
};
middleware(store)(next)(sampleAction);
expect(next).to.have.been.calledWith(sampleAction);
});

it(`should handle notify.about method on ${actionTypes.accountUpdated} action`, () => {
const spyFn = spy(Notification, 'about');
middleware(store)(next)(accountUpdatedAction(1000));
expect(spyFn).to.have.been.calledWith('deposit', 900);
spyFn.restore();
});

it(`should not handle notify.about method on ${actionTypes.accountUpdated} action if balance the same or lower than current`, () => {
const spyFn = spy(Notification, 'about');
middleware(store)(next)(accountUpdatedAction(100));
middleware(store)(next)(accountUpdatedAction(50));
expect(spyFn.called).to.be.equal(false);
spyFn.restore();
});
});

61 changes: 61 additions & 0 deletions src/utils/notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { fromRawLsk } from './lsk';
/**
* The Notify factory constructor class
* @class Notify
* @constructor
*/
class Notification {
constructor() {
this.isFocused = true;
}

/**
* Initialize event listeners
*
* @returns {this}
* @method init
* @memberof Notify
*/
init() {
if (PRODUCTION) {
const { ipc } = window;
ipc.on('blur', () => this.isFocused = false);
ipc.on('focus', () => this.isFocused = true);
}
return this;
}

/**
* Routing to specific Notification creator based on type param
* @param {string} type
* @param {any} data
*
* @method about
* @public
* @memberof Notify
*/
about(type, data) {
if (this.isFocused) return;
switch (type) {
case 'deposit':
this._deposit(data);
break;
default: break;
}
}

/**
* Creating notification about deposit
*
* @param {number} amount
* @private
* @memberof Notify
*/
_deposit(amount) { // eslint-disable-line
const body = `You've received ${fromRawLsk(amount)} LSK.`;
new window.Notification('LSK received', { body }); // eslint-disable-line
}
}

export default new Notification();

43 changes: 43 additions & 0 deletions src/utils/notification.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { expect } from 'chai';
import { spy } from 'sinon';
import { fromRawLsk } from './lsk';
import Notification from './notification';

describe('Notification', () => {
let notify;

beforeEach(() => {
notify = Notification.init();
});

describe('about(data)', () => {
const amount = 100000000;
const mockNotification = spy();

it('should call this._deposit', () => {
const spyFn = spy(notify, '_deposit');
notify.isFocused = false;
notify.about('deposit', amount);
expect(spyFn).to.have.been.calledWith(amount);
});

it('should call window.Notification', () => {
window.Notification = mockNotification;
const msg = `You've received ${fromRawLsk(amount)} LSK.`;

notify.isFocused = false;
notify.about('deposit', amount);
expect(mockNotification).to.have.been.calledWith(
'LSK received', { body: msg },
);
mockNotification.reset();
});

it('should not call window.Notification if app is focused', () => {
notify.isFocused = true;
notify.about('deposit', amount);
expect(mockNotification).to.have.been.not.calledWith();
mockNotification.reset();
});
});
});

0 comments on commit fa4c2ca

Please sign in to comment.