apitest 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0633ebdeafbf793f850ec77c572c6e10687c1aa
4
- data.tar.gz: c8a24eb02574bf285718e4b2a1ea651168e11193
3
+ metadata.gz: 573eef6c4af633b41ade5cf70edc2abb18676367
4
+ data.tar.gz: d128c020fe260b55e550d90b2e4c59089db4e63d
5
5
  SHA512:
6
- metadata.gz: 4f9234362ef3cb83cc44be3368aee0a21c8d6c82bbf1d1d2d5a67b28ffb010090372e4858aab9749071d7b719de690bfab6a3c36e7d60279200d386fc0a2f994
7
- data.tar.gz: b96dc2f3036ffd72dec49ab2744cd491ffab60b8f92e059b361e268801c35e78588ba419248d1b71a197029fc75ba7d8b0f9235ecff95239070255642414ba5f
6
+ metadata.gz: d1b50589b5877b6f1c96d8bfc00d86962a96e3954d7da75e5667a34eb514d7e872a49372f25607b146a5d2cf430837575148f02585fd0e0c1bd7efbc8a0dc265
7
+ data.tar.gz: fcb4faabaad7d12e54d5ffb56320f721b3214a5b92ae35da169b25dbb6a9ad35f986dca6bfb6ab171460ee130cbd77b4790174e9f4e04b65dc12d89602b0053a
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Apitest
2
- - 通过在API controller里的常量,配置API文档
2
+ - 通过在API controller里配置常量,生成API文档
3
3
  - 并附带一个测试界面,辅助API开发。
4
4
  - 适用与API开发人员,客户端/前端开发人员交流验证文档。
5
- - 目前无出参,需要提交后,得到无法完全替代API文档
5
+ - 目前无出参,需要提交后,得到。无法完全替代API文档
6
6
 
7
7
  ## Version
8
- 0.1.9
8
+ 0.2.0
9
9
 
10
10
  ## Installation
11
11
  添加如下代码到 Gemfile:
@@ -137,14 +137,71 @@ Rails.application.routes.draw do
137
137
  end
138
138
  ```
139
139
 
140
+ 如果所有API有公共必填项,例如token,version,可如下配置
141
+
142
+ ```ruby
143
+ Rails.application.routes.draw do
144
+
145
+ apitest_for '/apitest' do
146
+ Apitest::public_required [ 'token' , 'version' ]
147
+ end
148
+
149
+ end
150
+ ```
151
+
152
+ 可以在指定APITEST中关闭公共必填项,比如登录API,可在具体方法的APIDOC中使用false设定
153
+
154
+ ```ruby
155
+ token:false
156
+ ```
157
+
158
+ 完整配置方法如下
159
+ ```ruby
160
+ class Api::V1::LoginController < ApplicationController
161
+
162
+ APIDOC = {
163
+ type: '业务API' ,
164
+ group_name: '用户登录' ,
165
+ sort: 1 ,
166
+ apis: {
167
+ create: {
168
+ api_name: '登录' ,
169
+ path: '/api/v1/login' ,
170
+ method: 'post' ,
171
+ token: false , # 这里可关闭该API的token选项
172
+ params: {
173
+ mobile: {
174
+ required: true ,
175
+ } ,
176
+ password: {
177
+ required: true
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
+ def create
184
+ ...
185
+ end
186
+
187
+ ```
188
+
189
+
190
+
191
+
192
+
193
+
140
194
 
141
195
 
142
196
  ## TODO
143
197
  - [x] 可自定义api目录
144
198
  - [x] 可自定义theme
145
199
  - [x] 可配置分类
146
- - [ ] 可设定所有API都有的必填项,比如token、客户端类型、客户端版本号
200
+ - [x] 可设定公共必填项,比如token、客户端类型、客户端版本号
201
+ - [x] 公共必填项可在指定API中关闭
202
+ - [x] 支持header token和params token
147
203
  - [ ] ERROR类工具
204
+ - [ ] 出参example
148
205
  - [ ] Apitest Example 网站
149
206
  - [ ] 使用前端route
150
207
  - [ ] 生成前端mock数据
@@ -5,6 +5,7 @@
5
5
  #= require jquery3
6
6
  #= require jquery_ujs
7
7
  #= require turbolinks
8
+ #= require lodash
8
9
  #= require bootstrap
9
10
  #= require adminlte/adminlte
10
11
  #= require vue
@@ -17,6 +18,7 @@ $(document).on "turbolinks:load" , ->
17
18
  vm = new Vue
18
19
  el : '#apitest_show'
19
20
  data :
21
+ apitest_tab_show : 'api_test'
20
22
  root_url : null
21
23
  apis : null
22
24
  ws : null
@@ -24,21 +26,39 @@ $(document).on "turbolinks:load" , ->
24
26
  current_group : ''
25
27
  current_api : ''
26
28
  token : ''
27
- apitest_tab_show : 'api_test'
29
+ token_type : ''
30
+ token_set : {}
31
+ token_get : []
32
+ headers : {}
28
33
  mounted : ->
29
34
  @apis = $('#data').data('apis')
30
- @token = $('#data').data('token')
35
+ @token_set = $('#data').data('token-set')
36
+ @token_get = $('#data').data('token-get')
37
+ @token_type = @token_set[0]
31
38
  @output_area = $('#server-logs-output')
32
39
  @root_url = $('#data').data('root-url')
33
40
  @get_log()
41
+ @set_token(localStorage.apitest_token)
42
+ # @token_set()
34
43
 
35
44
  methods :
36
-
45
+ set_token : (token) ->
46
+ @token = token
47
+ localStorage.apitest_token = token
48
+ @set_header_token() if @token_set[0] == 'header'
49
+
50
+ set_header_token : ->
51
+ @headers[@token_set[1]] = @token
52
+
53
+ fetch_token : (params) ->
54
+ token = eval 'params["' + @token_get.join('"]["') + '"]'
55
+ @set_token(token) if token
56
+
37
57
  group_select : (name) ->
38
58
  @current_group = name
39
59
  @current_api = ''
40
60
 
41
- api_select : (name ) ->
61
+ api_select : (name) ->
42
62
  @current_api = name
43
63
 
44
64
  api_submit : (e) ->
@@ -50,17 +70,23 @@ $(document).on "turbolinks:load" , ->
50
70
  postData = {}
51
71
 
52
72
  elm.find('.params').each ->
53
-
54
73
  postData[$(this).attr('name')] = $(this).val() unless $(this).attr('name').indexOf(':id') >= 0
55
-
74
+
56
75
  $.ajax
57
76
  url : path
58
77
  type : method
59
78
  data : postData
79
+ headers : @headers
60
80
  success : (data) =>
61
81
  result_pre.jsonViewer(data)
82
+ @fetch_token(data)
62
83
  error : (data) =>
63
- result.val data.responseText
84
+ try
85
+ result_pre.jsonViewer(JSON.parse(data.responseText))
86
+ catch e
87
+ result_pre.text(data.responseText)
88
+
89
+
64
90
 
65
91
  clear_result : (e) ->
66
92
  $(e.target).parents('.api').find('.result_pre').html('')
@@ -24,6 +24,8 @@
24
24
  background-color: #fff;
25
25
  height: 514px;
26
26
  border-radius: 0px;
27
+ white-space: pre-wrap;
28
+ word-wrap: break-word;
27
29
  padding: 15px 30px 15px 30px;
28
30
  }
29
31
  .nav-pills.nav-stacked{
@@ -5,7 +5,10 @@ module Apitest
5
5
  before_action :get_doc ,:root_url
6
6
  def initialize
7
7
  super
8
- @apidocs = {}
8
+ @apidocs = {}
9
+ @headers = Apitest::set_headers
10
+ @token_set = Apitest::token_setting[:set]
11
+ @token_get = Apitest::token_setting[:get]
9
12
  end
10
13
  def index
11
14
  respond_to do |format|
@@ -29,24 +32,24 @@ module Apitest
29
32
  def get_doc(path_root = nil)
30
33
  path_root ||= "app/controllers/#{Apitest.api_dir}/"
31
34
  Dir.glob("#{path_root}*").each do |path|
32
- @apidocs[path.gsub("#{path_root}" , '')] = get_version_doc "#{path}/" if File.directory?(path) && !path.gsub("#{path_root}" , '').blank?
35
+ @apidocs[path.gsub("#{path_root}" , '')] = get_version_doc "#{path}" if File.directory?(path) && !path.gsub("#{path_root}" , '').blank?
33
36
  end
34
37
  end
35
38
 
36
- def get_version_doc(path_root)
37
- docs = Apitest::default_types.clone
39
+ def get_version_doc(path_root , docs = {})
40
+ docs = Apitest::default_types.clone if docs.blank?
38
41
  Dir.glob("#{path_root}/*").each do |path|
39
42
  if File.directory?(path)
40
- docs = docs.merge get_version_doc(path)
43
+ docs = docs.merge get_version_doc(path , docs)
41
44
  else
42
45
  class_match = File.open(path).read.match(/class (.*) </)
43
46
  controller_class = class_match[1].constantize if class_match && class_match[1]
44
47
  if defined? controller_class::APIDOC
45
- doc = controller_class::APIDOC
46
- doc[:sort] = 99 if doc[:sort].blank?
48
+ doc = controller_class::APIDOC
49
+ doc[:sort] = 99 if doc[:sort].blank?
47
50
  doc[:apis].each do |k,v|
48
51
  d = doc[:apis][k]
49
- d = public_required d unless Apitest::public_required.blank?
52
+ d = public_required d unless Apitest::public_required.blank?
50
53
  d[:params] = {':id' => { required: true }}.merge d[:params] if d[:path].include? ':id'
51
54
  end
52
55
 
@@ -55,13 +58,13 @@ module Apitest
55
58
  end
56
59
  end
57
60
  end
58
- docs
61
+ return docs
59
62
  end
60
63
  def public_required(api)
61
64
  Apitest::public_required.reverse.each do |need|
62
65
  api[:params] = need.merge api[:params] if api[need.keys.first.to_sym] != false
63
66
  end
64
- api
67
+ return api
65
68
  end
66
69
  end
67
70
  end
@@ -66,24 +66,44 @@ section.content
66
66
  td 参数
67
67
  td
68
68
  table.table.table-hover.table-bordered
69
+ tr v-if="token_type == 'params'"
70
+ td
71
+ span style="color:red;width:10px;display:inline-block"
72
+ span *
73
+ span token
74
+ td
75
+ input.form-control.params name="token" :value="token"
69
76
  tr v-for="(value , name , index) in api.params"
70
- td.col-md-2 v-bind:class="{'border-top-none': (index == 0)}"
77
+ td.col-md-2
71
78
  span style="color:red;width:10px;display:inline-block"
72
79
  span v-if="value.required" *
73
80
  span ="{{name}}"
74
- td v-if="name == 'token'" v-bind:class="{'border-top-none': index == 0}"
75
- input.form-control.params :name="name" :value="token"
76
- span style="line-height:25px" = "{{value.text}}"
77
- td v-if="name != 'token'" v-bind:class="{'border-top-none': index == 0}"
81
+ td v-if="value.nested == true"
82
+ table.table.table-hover
83
+ tr v-for="(v , n , i) in value" v-if="n != 'nested'"
84
+ td.col-md-3
85
+ span style="color:red;width:10px;display:inline-block"
86
+ span v-if="v.required" *
87
+ span ="{{name}}[{{n}}]"
88
+ td
89
+ input.form-control.params :name="name + '[' + n + ']'"
90
+ span style="line-height:25px" = "{{v.text}}"
91
+ td v-else=""
78
92
  input.form-control.params :name="name"
79
93
  span style="line-height:25px" = "{{value.text}}"
94
+ / td v-if="name == 'token'" v-bind:class="{'border-top-none': index == 0}"
95
+ / input.form-control.params :name="name" :value="token"
96
+ / span style="line-height:25px" = "{{value.text}}"
97
+ / td v-if="name != 'token'" v-bind:class="{'border-top-none': index == 0}"
98
+ / input.form-control.params :name="name"
99
+ / span style="line-height:25px" = "{{value.text}}"
80
100
  tr
81
101
  td
82
102
  td
83
103
  button.btn.bg-olive.btn-flat @click="api_submit" 提交
84
- button.btn.bg-orange.btn-flat style="margin-left:10px;margin-right:10px" @click="clear_result" 清空结果
85
- button.btn.bg-purple.btn-flat style="margin-left:10px;margin-right:10px" @click="show_server_log" 查看server log
86
- button.btn.btn-warning.btn-flat style="margin-right:10px" @click="clear_log" 清空log
104
+ button.btn.bg-orange.btn-flat style="margin-left:10px;margin-right:10px" @click="clear_result" 清空结果
105
+ button.btn.bg-purple.btn-flat style="margin-left:10px;margin-right:10px" @click="show_server_log" 查看server log
106
+ button.btn.btn-warning.btn-flat style="margin-right:10px" @click="clear_log" 清空log
87
107
  tr
88
108
  td
89
109
  td
@@ -31,6 +31,6 @@ html
31
31
  =yield
32
32
  footer.main-footer
33
33
  -if params[:action] == 'show'
34
- #data data-root-url="#{@root_url}" data-ws-url="ws://#{request.host}:9527" data-apis="#{@apidocs[params[:id]].to_json}" data-token="#{session[:token]}"
34
+ #data data-root-url="#{@root_url}" data-ws-url="ws://#{request.host}:9527" data-apis="#{@apidocs[params[:id]].to_json}" data-headers="#{@headers.to_json}" data-token-set="#{@token_set.to_json}" data-token-get="#{@token_get.to_json}"
35
35
 
36
36
 
@@ -7,6 +7,7 @@ require "font-awesome-rails"
7
7
  require "ionicons-rails"
8
8
  require 'eventmachine'
9
9
  require 'eventmachine-tail'
10
+ require 'lodash-rails'
10
11
  require 'websocket-eventmachine-server'
11
12
 
12
13
  module Apitest
@@ -14,6 +15,8 @@ module Apitest
14
15
  @theme
15
16
  @default_types
16
17
  @public_required
18
+ @token_setting
19
+
17
20
  class << self
18
21
  def api_dir(dir = nil)
19
22
  @api_dir = dir if dir
@@ -44,6 +47,15 @@ module Apitest
44
47
  @public_required
45
48
  end
46
49
 
50
+ def token_setting(setting = nil)
51
+ @token_setting = setting if setting
52
+ @token_setting
53
+ end
54
+
55
+ def set_headers
56
+ @token_setting[:set] && @token_setting[:set][1] ? {@token_setting[:set][1] => ''} : {}
57
+ end
58
+
47
59
  def start_server_log_listen
48
60
  Process.detach(
49
61
  fork do
@@ -68,18 +80,6 @@ module Apitest
68
80
  )
69
81
  end
70
82
  end
71
-
72
- class Reader < EventMachine::FileTail
73
- def initialize(path, startpos=-1, &block)
74
- super(path, startpos)
75
- @buffer = BufferedTokenizer.new
76
- @block = block
77
- end
78
-
79
- def receive_data(data)
80
- @buffer.extract(data).each { |line| @block.call(line) }
81
- end
82
- end
83
83
  end
84
84
 
85
85
  module ActionDispatch::Routing
@@ -0,0 +1,35 @@
1
+ module Apitest
2
+ module Error
3
+ def error(error_code = nil , data = nil,message = nil)
4
+ hash = {
5
+ status: 'error' ,
6
+ error_code: error_code ,
7
+ message: message.nil? ? self::ERROR[error_code] : message ,
8
+ data: data ,
9
+ }
10
+ raise "#{self.to_s}::Error".constantize.new hash
11
+ end
12
+
13
+ def success(message = nil , data = nil)
14
+ hash = {}
15
+ hash[:status] = 'ok'
16
+ if message.is_a? Hash
17
+ hash[:message] = message[:message] ? message[:message] : ''
18
+ hash[:data] = message[:data] ? message[:data] : message
19
+ else
20
+ hash[:message] = message ? message : ''
21
+ hash[:data] = data ? data : {}
22
+ end
23
+ return hash
24
+ end
25
+
26
+ class Error < StandardError
27
+ def error
28
+ eval(message)
29
+ end
30
+ def error_code
31
+ error[:error_code]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module Apitest
2
+ module ModelError
3
+ include Apitest::Error
4
+ def self.include(klass)
5
+ klass.class_eval do
6
+ include ServiceError
7
+ extend ServiceError
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Apitest
2
+ class Reader < EventMachine::FileTail
3
+ def initialize(path, startpos=-1, &block)
4
+ super(path, startpos)
5
+ @buffer = BufferedTokenizer.new
6
+ @block = block
7
+ end
8
+
9
+ def receive_data(data)
10
+ @buffer.extract(data).each { |line| @block.call(line) }
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,41 @@
1
+ module Apitest
2
+ module ServiceError
3
+ # include Apitest::Error
4
+ def self.include(klass)
5
+ klass.class_eval do
6
+ include ServiceError
7
+ extend ServiceError
8
+ end
9
+ end
10
+ def self.error(error_code = nil , data = nil,message = nil)
11
+ hash = {
12
+ status: 'error' ,
13
+ error_code: error_code ,
14
+ message: message.nil? ? self::ERROR[error_code] : message ,
15
+ data: data ,
16
+ }
17
+ raise "#{self.to_s}::Error".constantize.new hash
18
+ end
19
+
20
+ def success(message = nil , data = nil)
21
+ hash = {}
22
+ hash[:status] = 'ok'
23
+ if message.is_a? Hash
24
+ hash[:message] = message[:message] ? message[:message] : ''
25
+ hash[:data] = message[:data] ? message[:data] : message
26
+ else
27
+ hash[:message] = message ? message : ''
28
+ hash[:data] = data ? data : {}
29
+ end
30
+ return hash
31
+ end
32
+ class Error < StandardError
33
+ def error
34
+ eval(message)
35
+ end
36
+ def error_code
37
+ error[:error_code]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Apitest
2
- VERSION = '0.1.9'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apitest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyuubi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-30 00:00:00.000000000 Z
11
+ date: 2017-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: lodash-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: eventmachine-tail
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -179,6 +193,10 @@ files:
179
193
  - config/routes.rb
180
194
  - lib/apitest.rb
181
195
  - lib/apitest/engine.rb
196
+ - lib/apitest/error.rb
197
+ - lib/apitest/module_error.rb
198
+ - lib/apitest/reader.rb
199
+ - lib/apitest/service_error.rb
182
200
  - lib/apitest/version.rb
183
201
  - lib/tasks/apitest_tasks.rake
184
202
  homepage: https://github.com/kyuubi9/apitest