Skip to content

Commit 14da35c

Browse files
authored
Jest, feather, Semantic UI updates (#1)
* update dependencies - feather, jest, etc. use cross-env instead of better-npm-run * use resolve/alias to solve semantic-ui-less path issue. update semantic-ui-react to ^0.79.0 * set NODE_ENV=test https://stackoverflow.com/questions/43916941/ * just test without api test to see if it works with travis-ci * disable API test to test travis-ci timeout issue * reenable API test and remove NODE_ENV=TEST * DISABLE ACTION TEST. Again travis-ci * update node engine from 5 to 6.9.0 * set yarn version to run 1.5.1 * test-node don't set NODE_ENV to test * use npm instead of yarn * use npm instead of yarn * yarn with travis use yarn 1.3.2 and try node 9 * removed mocha disable two action tests. * try jest --forceExit * try to remove two tests * try test different one * set jest verbose * set jest debug * update sinon to 4.5.0 * Yes. It's because sinon. Need ^4.5.0 Move all test cases
1 parent b433ae6 commit 14da35c

File tree

21 files changed

+197
-207
lines changed

21 files changed

+197
-207
lines changed

.eslintrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"env": {
44
"browser": true,
55
"node": true,
6-
"mocha": true,
6+
"jest": true,
77
"es6": true
88
},
99
"rules": {

.travis.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,18 @@ before_script:
2828
- export DISPLAY=:99.0
2929
- sh -e /etc/init.d/xvfb start
3030
- export NODE_ENV=development
31+
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.3.2
32+
- export PATH="$HOME/.yarn/bin:$PATH"
3133

3234
cache:
3335
yarn: true
3436
directories:
3537
- node_modules
3638

3739
script:
40+
- yarn test-node
3841
- yarn lint
3942
- yarn test
40-
- yarn test-node
4143

4244
env:
4345
- TRAVIS=travis CXX=g++-4.8

README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ This is a starter boilerplate app I've put together using the following technolo
3636
* [font-awesome](https://github.com/FortAwesome/Font-Awesome)
3737
* [react-helmet](https://github.com/nfl/react-helmet) to manage title and meta tag information on both server and client
3838
* [webpack-isomorphic-tools](https://github.com/halt-hammerzeit/webpack-isomorphic-tools) to allow require() work for statics both on client and server
39-
* [Jest](https://facebook.github.io/jest/) and [mocha](https://mochajs.org/) to allow writing unit tests for the project.
40-
39+
* [Jest](https://facebook.github.io/jest/) to allow writing unit tests for the project.
4140
I cobbled this together from a wide variety of similar "starter" repositories. As I post this in June 2015, all of these libraries are right at the bleeding edge of web development. They may fall out of fashion as quickly as they have come into it, but I personally believe that this stack is the future of web development and will survive for several years. I'm building my new projects like this, and I recommend that you do, too.
4241

4342
## Features
@@ -243,7 +242,7 @@ After this modification to both loaders you will be able to use scss and less fi
243242
244243
#### Unit Tests
245244
246-
The project uses [Jest](https://facebook.github.io/jest/) with [Mocha](https://mochajs.org/) to run your unit tests.
245+
The project uses [Jest](https://facebook.github.io/jest/) to run your unit tests.
247246
248247
To run the tests in the project, just simply run `npm test` if you have `Chrome` installed, it will be automatically launched as a test service for you.
249248

api/api.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import feathers from 'feathers';
1+
import express from '@feathersjs/express';
2+
import feathers from '@feathersjs/feathers';
3+
import socketio from '@feathersjs/socketio';
24
import morgan from 'morgan';
35
import session from 'express-session';
46
import bodyParser from 'body-parser';
57
import cookieParser from 'cookie-parser';
6-
import hooks from 'feathers-hooks';
7-
import rest from 'feathers-rest';
8-
import socketio from 'feathers-socketio';
98
import config from './config';
109
import services from './services';
10+
import channels from './channels';
1111
import { actionHandler, logger, notFound, errorHandler } from './middleware';
1212
import auth from './services/authentication';
1313

1414
process.on('unhandledRejection', error => console.error(error));
1515

16-
const app = feathers();
16+
const app = express(feathers());
1717

1818
app
1919
.set('config', config)
@@ -28,12 +28,12 @@ app
2828
.use(bodyParser.urlencoded({ extended: true }))
2929
.use(bodyParser.json())
3030
// Core
31-
.configure(hooks())
32-
.configure(rest())
31+
.configure(express.rest())
3332
.configure(socketio({ path: '/ws' }))
3433
.configure(auth)
3534
.use(actionHandler(app))
3635
.configure(services)
36+
.configure(channels)
3737
// Final handlers
3838
.use(notFound())
3939
.use(logger(app))
@@ -56,12 +56,7 @@ const messageBuffer = new Array(bufferSize);
5656
let messageIndex = 0;
5757

5858
app.io.on('connection', socket => {
59-
if (!socket._feathers) {
60-
// https://github.com/feathersjs/authentication/pull/604
61-
socket._feathers = {};
62-
}
63-
const user = socket.feathers.user ? { ...socket.feathers.user, password: undefined } : undefined;
64-
socket.emit('news', { msg: "'Hello World!' from server", user });
59+
socket.emit('news', { msg: "'Hello World!' from server" });
6560

6661
socket.on('history', () => {
6762
for (let index = 0; index < bufferSize; index += 1) {

api/channels.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export default app => {
2+
if (typeof app.channel !== 'function') {
3+
// If no real-time functionality has been configured just return
4+
return;
5+
}
6+
7+
app.on('connection', connection => {
8+
// On a new real-time connection, add it to the anonymous channel
9+
app.channel('anonymous').join(connection);
10+
});
11+
12+
app.on('login', (payload, { connection }) => {
13+
// connection can be undefined if there is no
14+
// real-time connection, e.g. when logging in via REST
15+
if (connection) {
16+
// Obtain the logged in user from the connection
17+
// const user = connection.user;
18+
19+
// The connection is no longer anonymous, remove it
20+
app.channel('anonymous').leave(connection);
21+
22+
// Add it to the authenticated user channel
23+
app.channel('authenticated').join(connection);
24+
25+
// Channels can be named anything and joined on any condition
26+
27+
// E.g. to send real-time events only to admins use
28+
// if(user.isAdmin) { app.channel('admins').join(connection); }
29+
30+
// If the user has joined e.g. chat rooms
31+
// if(Array.isArray(user.rooms)) user.rooms.forEach(room => app.channel(`rooms/${room.id}`).join(channel));
32+
33+
// Easily organize users by email and userid for things like messaging
34+
// app.channel(`emails/${user.email}`).join(channel);
35+
// app.channel(`userIds/$(user.id}`).join(channel);
36+
}
37+
});
38+
39+
// eslint-disable-next-line no-unused-vars,arrow-body-style
40+
app.publish((data, context) => {
41+
// Here you can add event publishers to channels set up in `channels.js`
42+
// To publish only for a specific event use `app.publish(eventname, () => {})`
43+
// e.g. to publish all service events to all authenticated users use
44+
return app.channel('authenticated');
45+
});
46+
47+
// Here you can also add service specific event publishers
48+
// e..g the publish the `users` service `created` event to the `admins` channel
49+
// app.service('users').publish('created', () => app.channel('admins'));
50+
51+
// With the userid and email organization from above you can easily select involved users
52+
// app.service('messages').publish(() => {
53+
// return [
54+
// app.channel(`userIds/${data.createdBy}`),
55+
// app.channel(`emails/${data.recipientEmail}`)
56+
// ];
57+
// });
58+
};

api/hooks/validateHook.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import errors from 'feathers-errors';
1+
import errors from '@feathersjs/errors';
22
import { createAsyncValidator as validator } from 'utils/validation';
33

44
export default function validateHook(schema) {

api/middleware/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1+
export errorHandler from '@feathersjs/errors/handler';
12
export actionHandler from './actionHandler';
2-
export errorHandler from 'feathers-errors/handler';
33
export logger from './logger';
44
export notFound from './notFound';

api/middleware/notFound.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const errors = require('feathers-errors');
1+
const errors = require('@feathersjs/errors');
22

33
export default function notFound() {
44
return (req, res, next) => {

api/services/authentication/index.js

+7-25
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import auth from 'feathers-authentication';
2-
import jwt from 'feathers-authentication-jwt';
3-
import local from 'feathers-authentication-local';
4-
// import oauth1 from 'feathers-authentication-oauth1';
5-
import oauth2 from 'feathers-authentication-oauth2';
1+
import auth from '@feathersjs/authentication';
2+
import jwt from '@feathersjs/authentication-jwt';
3+
import local from '@feathersjs/authentication-local';
4+
// import oauth1 from '@feathersjs/authentication-oauth1';
5+
import oauth2 from '@feathersjs/authentication-oauth2';
6+
67
import FacebookTokenStrategy from 'passport-facebook-token';
78
import { discard } from 'feathers-hooks-common';
89

@@ -14,25 +15,6 @@ function populateUser(authConfig) {
1415
};
1516
}
1617

17-
function restToSocketAuth() {
18-
return hook => {
19-
if (hook.params.provider !== 'rest') return hook;
20-
const { accessToken, user } = hook.result;
21-
const { socketId } = hook.data;
22-
if (socketId && hook.app.io && accessToken) {
23-
const userSocket = Object.values(hook.app.io.sockets.connected).find(socket => socket.client.id === socketId);
24-
if (userSocket) {
25-
Object.assign(userSocket.feathers, {
26-
accessToken,
27-
user,
28-
authenticated: true
29-
});
30-
}
31-
}
32-
return hook;
33-
};
34-
}
35-
3618
export default function authenticationService() {
3719
const app = this;
3820

@@ -54,7 +36,7 @@ export default function authenticationService() {
5436
remove: auth.hooks.authenticate('jwt')
5537
},
5638
after: {
57-
create: [populateUser(config), discard('user.password'), restToSocketAuth()]
39+
create: [populateUser(config), discard('user.password')]
5840
}
5941
});
6042
}

api/services/messages/hooks.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { disallow, discard, populate } from 'feathers-hooks-common';
2-
import auth from 'feathers-authentication';
1+
import auth from '@feathersjs/authentication';
2+
import { disallow, populate } from 'feathers-hooks-common';
33
import { required } from 'utils/validation';
44
import { validateHook as validate } from 'hooks';
55

@@ -43,9 +43,9 @@ const messagesHooks = {
4343
},
4444
after: {
4545
all: [],
46-
find: [populateUser(), discard('sentBy.password')],
47-
get: [populateUser(), discard('sentBy.password')],
48-
create: [populateUser(), discard('sentBy.password')],
46+
find: populateUser(),
47+
get: populateUser(),
48+
create: populateUser(),
4949
update: [],
5050
patch: [],
5151
remove: []

api/services/messages/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ export default function messagesService() {
1919
app.use('/messages', feathersNedb(options));
2020

2121
app.service('messages').hooks(hooks);
22+
app.service('messages').publish('created', () => app.channel('authenticated'));
2223
}

api/services/users/hooks.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { discard, iff, isProvider } from 'feathers-hooks-common';
2-
import auth from 'feathers-authentication';
3-
import local from 'feathers-authentication-local';
1+
import auth from '@feathersjs/authentication';
2+
import local from '@feathersjs/authentication-local';
3+
import errors from '@feathersjs/errors';
44
import { restrictToOwner } from 'feathers-authentication-hooks';
5-
import errors from 'feathers-errors';
5+
import { discard } from 'feathers-hooks-common';
66
import { validateHook } from 'hooks';
77
import { required, email, match, unique } from 'utils/validation';
88

@@ -31,7 +31,7 @@ const userHooks = {
3131
remove: [auth.hooks.authenticate('jwt'), restrictToOwner({ ownerField: '_id' })]
3232
},
3333
after: {
34-
all: iff(isProvider('external'), discard('password')),
34+
all: local.hooks.protect('password'),
3535
find: [],
3636
get: [],
3737
create: [],

0 commit comments

Comments
 (0)