lrf402788946 před 5 roky
revize
f309436ef7

+ 29 - 0
.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
README.md

@@ -0,0 +1,33 @@
+# service-market
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 36 - 0
app/controller/.chat.js

@@ -0,0 +1,36 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "sender_id",
+      "sender_name",
+      "!content",
+      "send_time",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [ "sender_id", "sender_name", "content", "send_time"],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: [ "sender_id", "sender_name", "content", "send_time"],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      asc: true,
+      count: true,
+    },
+  },
+};

+ 31 - 0
app/controller/.present.js

@@ -0,0 +1,31 @@
+module.exports = {
+  create: {
+    requestBody: ["!name", "!price"],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: ["name", "price"],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: ["name", "price"],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 55 - 0
app/controller/.presentrcord.js

@@ -0,0 +1,55 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "!owner_id",
+      "!owner_name",
+      "!sender_id",
+      "!sender_name",
+      "!present_id",
+      "!present_name",
+      "!price",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [
+      "owner_id",
+      "owner_name",
+      "sender_id",
+      "sender_name",
+      "present_id",
+      "present_name",
+      "price",
+    ],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: [
+        "owner_id",
+        "owner_name",
+        "sender_id",
+        "sender_name",
+        "present_id",
+        "present_name",
+        "price",
+      ],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 43 - 0
app/controller/.room.js

@@ -0,0 +1,43 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "!number",
+      "!owner_id",
+      "!owner_name",
+      "room_status",
+      "live_status",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [
+      "number",
+      "owner_id",
+      "owner_name",
+      "room_status",
+      "live_status",
+    ],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: ["number","owner_id","owner_name", "room_status", "live_status"],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 37 - 0
app/controller/.roomchat.js

@@ -0,0 +1,37 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "!number",
+      "!sender_id",
+      "!sender_name",
+      "!content",
+      "!send_time",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: ["number", "sender_id", "sender_name", "content", "send_time"],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: ["number","sender_id", "sender_name", "content", "send_time"],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 16 - 0
app/controller/chat.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.chat.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 公共聊天表管理
+class ChatController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.chat;
+  }
+}
+
+module.exports = CrudController(ChatController, meta);

+ 12 - 0
app/controller/home.js

@@ -0,0 +1,12 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class HomeController extends Controller {
+  async index() {
+    const { ctx } = this;
+    ctx.body = 'hi, egg';
+  }
+}
+
+module.exports = HomeController;

+ 16 - 0
app/controller/present.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.present.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 礼物字典表管理
+class PresentController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.present;
+  }
+}
+
+module.exports = CrudController(PresentController, meta);

+ 16 - 0
app/controller/presentrcord.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.presentrcord.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 礼物记录表管理
+class PresentrcordController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.presentrcord;
+  }
+}
+
+module.exports = CrudController(PresentrcordController, meta);

+ 16 - 0
app/controller/room.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.room.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 房间表管理
+class RoomController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.room;
+  }
+}
+
+module.exports = CrudController(RoomController, meta);

+ 16 - 0
app/controller/roomchat.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.roomchat.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 房间聊天表管理
+class RoomchatController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.roomchat;
+  }
+}
+
+module.exports = CrudController(RoomchatController, meta);

+ 18 - 0
app/model/chat.js

@@ -0,0 +1,18 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+
+const Chat = {
+  sender_id: { type: String, maxLength: 200 }, // 发言人id
+  sender_name: { type: String, required: true, maxLength: 200 }, // 发言人名称
+  content: { type: String, required: true, maxLength: 1000 }, // 发言内容
+  send_time: { type: String, required: true, maxLength: 100 }, // 发言时间:年月日时分秒
+};
+const schema = new Schema(Chat, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Chat', schema, 'chat');
+};

+ 16 - 0
app/model/present.js

@@ -0,0 +1,16 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+
+const Present = {
+  name: { type: String, required: true, maxLength: 200 }, // 礼物名称
+  price: { type: String, required: true, maxLength: 200 }, // 金额
+};
+const schema = new Schema(Present, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('present', schema, 'present');
+};

+ 21 - 0
app/model/presentrcord.js

@@ -0,0 +1,21 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+
+const PresentRecord = {
+  owner_id: { type: String, required: true, maxLength: 200 }, // 播主id
+  owner_name: { type: String, required: true, maxLength: 200 }, // 播主名称
+  sender_id: { type: String, required: true, maxLength: 200 }, // 赠送人id
+  sender_name: { type: String, required: true, maxLength: 200 }, // 赠送人名称
+  present_id: { type: String, required: true, maxLength: 200 }, // 礼物id
+  present_name: { type: String, required: true, maxLength: 200 }, // 礼物名称
+  price: { type: String, required: true, maxLength: 200 }, // 金额
+};
+const schema = new Schema(PresentRecord, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('PresentRecord', schema, 'present_record');
+};

+ 19 - 0
app/model/room.js

@@ -0,0 +1,19 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+
+const Room = {
+  number: { type: String, required: true, maxLength: 200 }, // 房间号
+  owner_id: { type: String, required: true, maxLength: 200 }, // 播主id
+  owner_name: { type: String, required: true, maxLength: 200 }, // 播主名称
+  room_status: { type: String, default: '0', maxLength: 1 }, // 房间状态:0未审核;1可使用;2已冻结
+  live_status: { type: String, default: '0', maxLength: 1 }, // 直播状态:0已下播;1直播中
+};
+const schema = new Schema(Room, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Room', schema, 'live_room');
+};

+ 19 - 0
app/model/roomchat.js

@@ -0,0 +1,19 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+
+const RoomChat = {
+  number: { type: String, required: true, maxLength: 200 }, // 房间号
+  sender_id: { type: String, required: true, maxLength: 200 }, // 发言人id
+  sender_name: { type: String, required: true, maxLength: 200 }, // 发言人名称
+  content: { type: String, required: true, maxLength: 1000 }, // 发言内容
+  send_time: { type: String, required: true, maxLength: 100 }, // 发言时间:年月日时分秒
+};
+const schema = new Schema(RoomChat, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('RoomChat', schema, 'room_chat');
+};

+ 33 - 0
app/router.js

@@ -0,0 +1,33 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  router.get('/', controller.home.index);
+
+  // 礼物表设置路由
+  router.resources('present', '/api/live/present', controller.present); // index、create、show、destroy
+  router.post('present', '/api/live/present/:id', controller.present.update);
+
+  // 礼物表设置路由
+  router.resources('presentrcord', '/api/live/presentrcord', controller.presentrcord); // index、create、show、destroy
+  router.post('presentrcord', '/api/live/presentrcord/:id', controller.presentrcord.update);
+
+
+  // 房间表设置路由
+  router.resources('room', '/api/live/room', controller.room); // index、create、show、destroy
+  router.post('room', '/api/live/room/:id', controller.room.update);
+
+  // 房间表设置路由
+  router.resources('roomchat', '/api/live/roomchat', controller.roomchat); // index、create、show、destroy
+  router.post('roomchat', '/api/live/roomchat/:id', controller.roomchat.update);
+
+
+  // 房间表设置路由
+  router.resources('chat', '/api/live/chat', controller.chat); // index、create、show、destroy
+  router.post('chat', '/api/live/chat/:id', controller.chat.update);
+
+
+};

+ 29 - 0
app/service/chat.js

@@ -0,0 +1,29 @@
+'use strict';
+
+const assert = require('assert');
+// const _ = require('lodash');
+// const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+// const { BusinessError, ErrorCode } = require('naf-core').Error;
+const moment = require('moment');
+class ChatService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'chat');
+    this.model = this.ctx.model.Chat;
+  }
+  async create(query, { sender_id, sender_name, content }) {
+    assert(sender_name, '缺少发言人信息');
+    assert(content, '缺少发言内容');
+    const send_time = moment().format('YYYY-MM-DD HH:mm:ss');
+    const res = await this.model.create({ sender_id, sender_name, content, send_time });
+    // TODO MQ
+    const { mq } = this.ctx;
+    if (mq) {
+      const exchange = 'public_chat';
+      await mq.topic(exchange, '', res.data, '');
+    }
+    return res;
+  }
+}
+
+module.exports = ChatService;

+ 16 - 0
app/service/present.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const assert = require('assert');
+// const _ = require('lodash');
+// const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+// const { BusinessError, ErrorCode } = require('naf-core').Error;
+
+class PresentService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'present');
+    this.model = this.ctx.model.Present;
+  }
+}
+
+module.exports = PresentService;

+ 16 - 0
app/service/presentrcord.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const assert = require('assert');
+// const _ = require('lodash');
+// const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+// const { BusinessError, ErrorCode } = require('naf-core').Error;
+
+class PresentrcordService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'present_record');
+    this.model = this.ctx.model.Presentrcord;
+  }
+}
+
+module.exports = PresentrcordService;

+ 16 - 0
app/service/room.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const assert = require('assert');
+// const _ = require('lodash');
+// const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+// const { BusinessError, ErrorCode } = require('naf-core').Error;
+
+class RoomService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'room');
+    this.model = this.ctx.model.Room;
+  }
+}
+
+module.exports = RoomService;

+ 16 - 0
app/service/roomchat.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const assert = require('assert');
+// const _ = require('lodash');
+// const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+// const { BusinessError, ErrorCode } = require('naf-core').Error;
+
+class RoomchatService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'roomchat');
+    this.model = this.ctx.model.Roomchat;
+  }
+}
+
+module.exports = RoomchatService;

+ 14 - 0
appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 61 - 0
config/config.default.js

@@ -0,0 +1,61 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+                               * built-in config
+                               * @type {Egg.EggAppConfig}
+                               **/
+  const config = (exports = {});
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys =
+                                appInfo.name + '_1579225760252_7743';
+
+  // add your middleware config here
+  config.middleware = [];
+
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+
+  // add your config here
+  config.cluster = {
+    listen: {
+      port: 9005,
+    },
+  };
+
+  config.mongoose = {
+    url: 'mongodb://localhost:27017/platform',
+    options: {
+      // user: 'demo',
+      // pass: 'demo',
+      // authSource: 'admin',
+      // useNewUrlParser: true,
+      // useCreateIndex: true,
+      // useUnifiedTopology: true,
+    },
+  };
+  // mq config
+  config.amqp = {
+    client: {
+      hostname: '127.0.0.1',
+      username: 'live',
+      password: '1qaz2wsx',
+      vhost: 'live',
+    },
+    app: true,
+    agent: true,
+  };
+
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 24 - 0
config/config.local.js

@@ -0,0 +1,24 @@
+'use strict';
+
+module.exports = () => {
+  const config = (exports = {});
+
+  config.logger = {
+    level: 'DEBUG',
+    consoleLevel: 'DEBUG',
+  };
+
+  config.mongoose = {
+    url: 'mongodb://localhost:27017/platform',
+    options: {
+      // user: 'demo',
+      // pass: 'demo',
+      // authSource: 'admin',
+      // useNewUrlParser: true,
+      // useCreateIndex: true,
+      // useUnifiedTopology: true,
+    },
+  };
+
+  return config;
+};

+ 12 - 0
config/config.prod.js

@@ -0,0 +1,12 @@
+'use strict';
+
+module.exports = () => {
+  const config = exports = {};
+
+  config.logger = {
+    // level: 'DEBUG',
+    // consoleLevel: 'DEBUG',
+  };
+
+  return config;
+};

+ 7 - 0
config/config.secret.js

@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = {
+  jwt: {
+    secret: 'Ziyouyanfa!@#',
+  },
+};

+ 7 - 0
config/plugin.js

@@ -0,0 +1,7 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+exports.amqp = {
+  enable: true,
+  package: 'egg-naf-amqp',
+};

+ 17 - 0
ecosystem.config.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const app = 'service-market';
+module.exports = {
+  apps: [{
+    name: app, // 应用名称
+    script: './server.js', // 实际启动脚本
+    out: `./logs/${app}.log`,
+    error: `./logs/${app}.err`,
+    watch: [ // 监控变化的目录,一旦变化,自动重启
+      'app', 'config',
+    ],
+    env: {
+      NODE_ENV: 'production', // 环境参数,当前指定为生产环境
+    },
+  }],
+};

+ 52 - 0
package.json

@@ -0,0 +1,52 @@
+{
+  "name": "service-live",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "framework": "naf-framework-mongoose"
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-scripts": "^2.11.0",
+    "lodash": "^4.17.15",
+    "moment": "^2.24.0",
+    "naf-framework-mongoose": "^0.6.11",
+    "silly-datetime": "^0.1.2",
+    "egg-naf-amqp": "0.0.13"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0",
+    "jsonwebtoken": "^8.5.1"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-service-market",
+    "stop": "egg-scripts stop --title=egg-server-service-market",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 9 - 0
server.js

@@ -0,0 +1,9 @@
+
+// eslint-disable-next-line strict
+const egg = require('egg');
+
+const workers = Number(process.argv[2] || require('os').cpus().length);
+egg.startCluster({
+  workers,
+  baseDir: __dirname,
+});

+ 20 - 0
test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});