Skip to content

Commit

Permalink
Merge pull request #1 from Baiang/test
Browse files Browse the repository at this point in the history
新增test分支
  • Loading branch information
Baiang committed Jul 21, 2018
2 parents 4b54eb1 + d7c83e7 commit 08575dc
Show file tree
Hide file tree
Showing 23 changed files with 309 additions and 45 deletions.
14 changes: 10 additions & 4 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
"transform-decorators-legacy"
],
"env": {
"test": {
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
}
}
"development": {
"presets": ["next/babel", "@zeit/next-typescript/babel"]
},
"production": {
"presets": ["next/babel", "@zeit/next-typescript/babel"]
},
"test": {
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }], "@zeit/next-typescript/babel"]
}
}
}
2 changes: 1 addition & 1 deletion __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { shallow } from 'enzyme'
import React from 'react'
import renderer from 'react-test-renderer'

import App from '../src/pages/index.jsx'
import App from '../src/pages/index.tsx'

describe('Home', () => {
it('App Home', () => {
Expand Down
17 changes: 17 additions & 0 deletions config/config.global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
development: {
staticUrl: '',
host: '127.0.0.1',
port: '3000',
},
test: {
staticUrl: '',
host: '0.0.0.0',
port: '3000',
},
production: {
staticUrl: '',
host: '0.0.0.0',
port: '3000',
}
};
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
"main": "index.js",
"scripts": {
"dev": "nodemon server/index.ts",
"dev:test": "nodemon server/index.ts",
"dev:eslint": "cross-env ANALYZE=ESLINT next src",
"build": "next build src",
"start": "next start src",
"build": "next build src && tsc --project tsconfig.server.json",
"start": "cross-env NODE_ENV=production node build/production-server/server/index.js",
"analyze:bundles": "cross-env ANALYZE=BUNDLES next build src",
"analyze:size": "cross-env ANALYZE=SIZE next build src",
"eslint": "eslint --fix --ext .jsx src/",
"lint:watch": "esw -w --fix --ext .js,.jsx,.tsx src/pages src/components",
"eslint": "eslint --fix --ext .jsx,.tsx src/",
"lint:watch": "esw -w --fix --ext .jsx,.tsx src/",
"test": "jest"
},
"keywords": [],
Expand Down Expand Up @@ -55,8 +54,11 @@
"eslint-plugin-standard": "^3.1.0",
"eslint-watch": "^4.0.1",
"file-loader": "^1.1.11",
"http-status": "^1.2.0",
"jest": "22.0.1",
"jest-transform-stub": "^1.0.0",
"koa-requestid": "^2.0.1",
"koa-router": "^7.4.0",
"nodemon": "^1.18.3",
"open-browser-webpack-plugin": "^0.0.5",
"postcss-import": "^11.1.0",
Expand All @@ -65,6 +67,7 @@
"react-test-renderer": "16.2.0",
"styled-jsx-plugin-sass": "^0.2.4",
"styled-jsx-postcss": "^0.2.0",
"supertest": "^3.1.0",
"ts-node": "^7.0.0",
"typescript": "^2.9.2",
"typescript-babel-jest": "^1.0.5",
Expand Down
1 change: 1 addition & 0 deletions server/controllers/mock.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.welcome = ctx => ctx.res.success('Hello!');
18 changes: 18 additions & 0 deletions server/helpers/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import chalk from 'chalk';
import moment from 'moment';

export const log = (color, level) => (message) => {
const prefix = `${moment().format()} [${level}] `;
if (typeof message === 'object') {
return console[level](chalk[color]('%o'), `${prefix}${message}`);
}
return console[level](chalk[color](`${prefix}${message}`));
};

export const debug = log('white', 'debug');

export const info = log('white', 'info');

export const warn = log('yellow', 'warn');

export const error = log('red', 'error');
83 changes: 52 additions & 31 deletions server/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,54 @@
import { createServer } from 'http'
import { parse } from 'url'
import * as next from 'next'
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const conf = require('../config/next.config.js')

const app = next({
import Koa from 'koa';
import next from 'next';
import bodyParser from 'koa-bodyparser';
import cors from 'kcors';
import helmet from 'koa-helmet';
import logger from 'koa-logger';

import * as log from './helpers/log';
import config from '../config/config.global';
// import requestId from './middleware/requestId';
import requestId from 'koa-requestid';
import responseHandler from './middleware/responseHandler';
import router from './routes';
// import conf from '../config/next.config.js';

const env = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
const dev = process.env.NODE_ENV !== 'production';


const nextApp = next({
dev,
conf,
dir:'./src'
})
const handle = app.getRequestHandler()

app.prepare()
.then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl

if (pathname === '/a') {
app.render(req, res, '/a', query)
} else if (pathname === '/b') {
app.render(req, res, '/b', query)
} else {
handle(req, res, parsedUrl)
}
})
.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
});

const handle = nextApp.getRequestHandler();
router.nextRoute(handle);
const app = new Koa();

app.use(logger());
app.use(bodyParser());
app.use(requestId());
app.use(helmet());
app.use(cors({
exposeHeaders: ['X-Request-Id']
}));
app.use(responseHandler());

if (!module.parent) {
nextApp.prepare()
.then(() => {
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(config[env].port, config[env].host, () => {
log.info(`API server listening on ${config[env].host}:${config[env].port}, in ${env}`);
});
});
} else {
// test
app.use(router.routes());
app.use(router.allowedMethods());
}
app.on('error', err => log.error(`Unhandled exception occured. message: ${err.message}`));

export default app;
22 changes: 22 additions & 0 deletions server/middleware/responseHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import httpStatus from 'http-status';

const responseHandler = () => async (ctx, next) => {
ctx.res.success = (data = null) => {
ctx.body = {
success: true,
code: httpStatus.OK,
data
};
};
ctx.res.failure = (code = null) => (message = null) => {
ctx.body = {
success: false,
code,
message
};
};
ctx.res.serverError = ctx.res.failure(httpStatus.INTERNAL_SERVER_ERROR);
await next();
};

export default responseHandler;
17 changes: 17 additions & 0 deletions server/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Router from 'koa-router';

// import mockController from './controllers/mock.controller';

const router = new Router();
// router.get('/api/get-welcome', mockController.welcome);

router.nextRoute = (handle) => {
router.get(/^(?!\/api)/, async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
});
};


export default router
// module.exports = router;
20 changes: 20 additions & 0 deletions server/test/integration/mock.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import supertest from 'supertest';
import httpStatus from 'http-status';
import app from '../../index';

/*describe("## Mock", () => {
const request = supertest(app.listen());
describe('# GET /api/get-welcome', () => {
it('should always return welcome string', async () => {
const res = await request
.get('/api/get-welcome')
.expect(httpStatus.OK);
const { success, code, data } = res.body;
expect(success).toBe(true);
expect(code).toBe(httpStatus.OK);
expect(data).toBe('Hello, OLAF!');
});
});
});*/
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/pages/about.jsx → src/pages/about.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Layout from '../index.jsx'
import Layout from '../index'

export default () => (
<Layout title="关于我们">
Expand Down
2 changes: 1 addition & 1 deletion src/pages/index.jsx → src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This is the Link API
import React, { Component } from 'react'
import Layout from '../index.jsx'
import Layout from '../index'

class Index extends Component {
constructor (props) {
Expand Down
26 changes: 26 additions & 0 deletions src/redux/actions/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const actionTypes = {
SELECT_DESCRIPTION: 'SELECT_DESCRIPTION',
REQUEST_INIT: 'REQUEST_INIT',
REQUEST_FAILURE: 'REQUEST_FAILURE',
RECEIVE_GETS: 'RECEIVE_GETS'
};

export const selectDescription = descriptionType => ({
type: actionTypes.SELECT_DESCRIPTION,
descriptionType
});

export const requestInit = selectedDescription => ({
type: actionTypes.REQUEST_INIT,
selectedDescription
});

export const requestFailure = error => ({
type: actionTypes.REQUEST_FAILURE,
error
});

export const requestSuccess = result => ({
type: actionTypes.RECEIVE_GETS,
data: result.data
});
35 changes: 35 additions & 0 deletions src/redux/reduces/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { fromJS } from 'immutable';

import { actionTypes } from '../actions/entries';
import { allDescriptionType } from '../../index.tsx';

const initialStateSelectedDescription = allDescriptionType[0];
export const selectedDescription = (state = initialStateSelectedDescription, action = {}) => {
switch (action.type) {
case actionTypes.SELECT_DESCRIPTION:
return action.descriptionType;
default:
return state;
}
};

const initialStateReceiveData = fromJS({
description: null,
error: null
});

export const receiveData = (state = initialStateReceiveData, action = {}) => {
switch (action.type) {
case actionTypes.RECEIVE_GETS:
return state.set('description', action.data.description);
case actionTypes.REQUEST_FAILURE:
return state.set('error', action.error);
default:
return state;
}
};

export const entriesState = {
selectedDescription: initialStateSelectedDescription,
receiveData: initialStateReceiveData
};
12 changes: 12 additions & 0 deletions src/redux/reduces/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { combineReducers } from 'redux';

import { selectedDescription, receiveData, entriesState } from './entries';

export const rootReducer = combineReducers({
selectedDescription,
receiveData
});

export const rootInitialState = {
...entriesState
};
16 changes: 16 additions & 0 deletions src/redux/sagas/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { put } from 'redux-saga/effects';

import { get } from '../../utilities/fetch';
import { requestFailure, requestSuccess } from '../actions/entries';

function* requestDataSaga({ selectedDescription }) {
try {
const res = yield get(selectedDescription);
const data = yield res.json();
yield put(requestSuccess(data));
} catch (err) {
yield put(requestFailure(err.message));
}
}

export default requestDataSaga;
12 changes: 12 additions & 0 deletions src/redux/sagas/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { all, takeLatest } from 'redux-saga/effects';

import requestDataSaga from './entries';
import { actionTypes } from '../actions/entries';

function* rootSaga() {
yield all([
takeLatest(actionTypes.REQUEST_INIT, requestDataSaga)
]);
}

export default rootSaga;
Loading

0 comments on commit 08575dc

Please sign in to comment.