appmap 0.48.0 → 0.51.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 +4 -4
- data/.dockerignore +0 -1
- data/CHANGELOG.md +43 -0
- data/README.md +3 -332
- data/lib/appmap.rb +33 -6
- data/lib/appmap/config.rb +123 -33
- data/lib/appmap/event.rb +1 -1
- data/lib/appmap/hook.rb +15 -30
- data/lib/appmap/minitest.rb +9 -3
- data/lib/appmap/railtie.rb +7 -0
- data/lib/appmap/rspec.rb +9 -3
- data/lib/appmap/util.rb +24 -1
- data/lib/appmap/version.rb +3 -1
- data/spec/abstract_controller_base_spec.rb +57 -18
- data/spec/config_spec.rb +21 -0
- data/spec/fixtures/hook/exception_method.rb +6 -0
- data/spec/fixtures/rails5_users_app/config/application.rb +0 -8
- data/spec/fixtures/rails5_users_app/spec/rails_helper.rb +0 -2
- data/spec/fixtures/rails6_users_app/config/application.rb +0 -8
- data/spec/fixtures/rails6_users_app/spec/rails_helper.rb +0 -2
- data/spec/hook_spec.rb +35 -3
- data/spec/record_net_http_spec.rb +1 -1
- data/test/bundle_vendor_test.rb +35 -0
- data/test/fixtures/bundle_vendor_app/Gemfile +8 -0
- data/test/fixtures/bundle_vendor_app/appmap.yml +4 -0
- data/test/fixtures/bundle_vendor_app/cli.rb +54 -0
- data/test/gem_test.rb +1 -1
- metadata +6 -4
- data/spec/fixtures/rails5_users_app/config/initializers/record_button.rb +0 -3
- data/spec/fixtures/rails6_users_app/config/initializers/record_button.rb +0 -3
data/lib/appmap/config.rb
CHANGED
@@ -167,8 +167,10 @@ module AppMap
|
|
167
167
|
),
|
168
168
|
package_hooks('actionpack',
|
169
169
|
[
|
170
|
-
method_hook('ActionDispatch::Request::Session', %i[
|
171
|
-
method_hook('ActionDispatch::
|
170
|
+
method_hook('ActionDispatch::Request::Session', %i[[] dig values fetch], %w[http.session.read]),
|
171
|
+
method_hook('ActionDispatch::Request::Session', %i[destroy[]= clear update delete merge], %w[http.session.write]),
|
172
|
+
method_hook('ActionDispatch::Cookies::CookieJar', %i[[]= clear update delete recycle], %w[http.session.read]),
|
173
|
+
method_hook('ActionDispatch::Cookies::CookieJar', %i[[]= clear update delete recycle], %w[http.session.write]),
|
172
174
|
method_hook('ActionDispatch::Cookies::EncryptedCookieJar', %i[[]= clear update delete recycle], %w[http.cookie crypto.encrypt])
|
173
175
|
],
|
174
176
|
package_name: 'action_dispatch'
|
@@ -213,15 +215,22 @@ module AppMap
|
|
213
215
|
# This is happening: Method send_command not found on Net::IMAP
|
214
216
|
# 'Net::IMAP' => TargetMethods.new(:send_command, Package.build_from_path('net/imap', package_name: 'net/imap', labels: %w[protocol.email.imap])),
|
215
217
|
# 'Marshal' => TargetMethods.new(%i[dump load], Package.build_from_path('marshal', labels: %w[format.marshal])),
|
216
|
-
'Psych' =>
|
217
|
-
|
218
|
-
|
218
|
+
'Psych' => [
|
219
|
+
TargetMethods.new(%i[load load_stream parse parse_stream], Package.build_from_path('yaml', package_name: 'psych', labels: %w[format.yaml.parse])),
|
220
|
+
TargetMethods.new(%i[dump dump_stream], Package.build_from_path('yaml', package_name: 'psych', labels: %w[format.yaml.generate])),
|
221
|
+
],
|
222
|
+
'JSON::Ext::Parser' => TargetMethods.new(:parse, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.parse])),
|
223
|
+
'JSON::Ext::Generator::State' => TargetMethods.new(:generate, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.generate])),
|
219
224
|
}.freeze
|
220
225
|
|
221
|
-
attr_reader :name, :packages, :exclude, :hooked_methods, :builtin_hooks
|
226
|
+
attr_reader :name, :appmap_dir, :packages, :exclude, :hooked_methods, :builtin_hooks
|
222
227
|
|
223
|
-
def initialize(name,
|
228
|
+
def initialize(name,
|
229
|
+
packages: [],
|
230
|
+
exclude: [],
|
231
|
+
functions: [])
|
224
232
|
@name = name
|
233
|
+
@appmap_dir = AppMap::DEFAULT_APPMAP_DIR
|
225
234
|
@packages = packages
|
226
235
|
@hook_paths = Set.new(packages.map(&:path))
|
227
236
|
@exclude = exclude
|
@@ -248,38 +257,119 @@ module AppMap
|
|
248
257
|
class << self
|
249
258
|
# Loads configuration data from a file, specified by the file name.
|
250
259
|
def load_from_file(config_file_name)
|
251
|
-
|
252
|
-
|
260
|
+
logo = lambda do
|
261
|
+
Util.color(<<~LOGO, :magenta)
|
262
|
+
___ __ ___
|
263
|
+
/ _ | ___ ___ / |/ /__ ____
|
264
|
+
/ __ |/ _ \\/ _ \\/ /|_/ / _ `/ _ \\
|
265
|
+
/_/ |_/ .__/ .__/_/ /_/\\_,_/ .__/
|
266
|
+
/_/ /_/ /_/
|
267
|
+
LOGO
|
268
|
+
end
|
269
|
+
|
270
|
+
config_present = true if File.exists?(config_file_name)
|
271
|
+
|
272
|
+
config_data = if config_present
|
273
|
+
require 'yaml'
|
274
|
+
YAML.safe_load(::File.read(config_file_name))
|
275
|
+
else
|
276
|
+
warn logo.()
|
277
|
+
warn ''
|
278
|
+
warn Util.color(%Q|NOTICE: The AppMap config file #{config_file_name} was not found!|, :magenta, bold: true)
|
279
|
+
warn ''
|
280
|
+
warn Util.color(<<~MISSING_FILE_MSG, :magenta)
|
281
|
+
AppMap uses this file to customize its behavior. For example, you can use
|
282
|
+
the 'packages' setting to indicate which local file paths and dependency
|
283
|
+
gems you want to include in the AppMap. Since you haven't provided specific
|
284
|
+
settings, the appmap gem will try and guess some reasonable defaults.
|
285
|
+
To suppress this message, create the file:
|
286
|
+
|
287
|
+
#{Pathname.new(config_file_name).expand_path}.
|
288
|
+
|
289
|
+
Here are the default settings that will be used in the meantime. You can
|
290
|
+
copy and paste this example to start your appmap.yml.
|
291
|
+
MISSING_FILE_MSG
|
292
|
+
{}
|
293
|
+
end
|
294
|
+
load(config_data).tap do |config|
|
295
|
+
config_yaml = {
|
296
|
+
'name' => config.name,
|
297
|
+
'packages' => config.packages.select{|p| p.path}.map do |pkg|
|
298
|
+
{ 'path' => pkg.path }
|
299
|
+
end,
|
300
|
+
'exclude' => []
|
301
|
+
}.compact
|
302
|
+
unless config_present
|
303
|
+
warn Util.color(YAML.dump(config_yaml), :magenta)
|
304
|
+
warn logo.()
|
305
|
+
end
|
306
|
+
end
|
253
307
|
end
|
254
308
|
|
255
309
|
# Loads configuration from a Hash.
|
256
310
|
def load(config_data)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
311
|
+
name = config_data['name'] || guess_name
|
312
|
+
config_params = {
|
313
|
+
exclude: config_data['exclude']
|
314
|
+
}.compact
|
315
|
+
|
316
|
+
if config_data['functions']
|
317
|
+
config_params[:functions] = config_data['functions'].map do |function_data|
|
318
|
+
package = function_data['package']
|
319
|
+
cls = function_data['class']
|
320
|
+
functions = function_data['function'] || function_data['functions']
|
321
|
+
raise %q(AppMap config 'function' element should specify 'package', 'class' and 'function' or 'functions') unless package && cls && functions
|
322
|
+
|
323
|
+
functions = Array(functions).map(&:to_sym)
|
324
|
+
labels = function_data['label'] || function_data['labels']
|
325
|
+
labels = Array(labels).map(&:to_s) if labels
|
326
|
+
Function.new(package, cls, labels, functions)
|
327
|
+
end
|
266
328
|
end
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
329
|
+
|
330
|
+
config_params[:packages] = \
|
331
|
+
if config_data['packages']
|
332
|
+
config_data['packages'].map do |package|
|
333
|
+
gem = package['gem']
|
334
|
+
path = package['path']
|
335
|
+
raise %q(AppMap config 'package' element should specify 'gem' or 'path', not both) if gem && path
|
336
|
+
|
337
|
+
if gem
|
338
|
+
shallow = package['shallow']
|
339
|
+
# shallow is true by default for gems
|
340
|
+
shallow = true if shallow.nil?
|
341
|
+
Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
|
342
|
+
else
|
343
|
+
Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
|
344
|
+
end
|
345
|
+
end.compact
|
277
346
|
else
|
278
|
-
|
347
|
+
Array(guess_paths).map do |path|
|
348
|
+
Package.build_from_path(path)
|
349
|
+
end
|
279
350
|
end
|
280
|
-
|
281
|
-
|
282
|
-
|
351
|
+
|
352
|
+
Config.new name, config_params
|
353
|
+
end
|
354
|
+
|
355
|
+
def guess_name
|
356
|
+
reponame = lambda do
|
357
|
+
next unless File.directory?('.git')
|
358
|
+
|
359
|
+
repo_name = `git config --get remote.origin.url`.strip
|
360
|
+
repo_name.split('/').last.split('.').first unless repo_name == ''
|
361
|
+
end
|
362
|
+
dirname = -> { Dir.pwd.split('/').last }
|
363
|
+
|
364
|
+
reponame.() || dirname.()
|
365
|
+
end
|
366
|
+
|
367
|
+
def guess_paths
|
368
|
+
if defined?(::Rails)
|
369
|
+
%w[app/controllers app/models]
|
370
|
+
elsif File.directory?('lib')
|
371
|
+
%w[lib]
|
372
|
+
end
|
283
373
|
end
|
284
374
|
end
|
285
375
|
|
@@ -289,7 +379,7 @@ module AppMap
|
|
289
379
|
packages: packages.map(&:to_h),
|
290
380
|
functions: @functions.map(&:to_h),
|
291
381
|
exclude: exclude
|
292
|
-
}
|
382
|
+
}.compact
|
293
383
|
end
|
294
384
|
|
295
385
|
# Determines if methods defined in a file path should possibly be hooked.
|
data/lib/appmap/event.rb
CHANGED
@@ -213,7 +213,7 @@ module AppMap
|
|
213
213
|
exception_backtrace = next_exception.backtrace_locations.try(:[], 0)
|
214
214
|
exceptions << {
|
215
215
|
class: best_class_name(next_exception),
|
216
|
-
message: next_exception.message,
|
216
|
+
message: display_string(next_exception.message),
|
217
217
|
object_id: next_exception.__id__,
|
218
218
|
path: exception_backtrace&.path,
|
219
219
|
lineno: exception_backtrace&.lineno
|
data/lib/appmap/hook.rb
CHANGED
@@ -36,7 +36,7 @@ module AppMap
|
|
36
36
|
|
37
37
|
def initialize(config)
|
38
38
|
@config = config
|
39
|
-
@
|
39
|
+
@trace_enabled = []
|
40
40
|
# Paths that are known to be non-tracing
|
41
41
|
@notrace_paths = Set.new
|
42
42
|
end
|
@@ -47,10 +47,8 @@ module AppMap
|
|
47
47
|
|
48
48
|
hook_builtins
|
49
49
|
|
50
|
-
@trace_begin = TracePoint.new(:class, &method(:trace_class))
|
51
50
|
@trace_end = TracePoint.new(:end, &method(:trace_end))
|
52
|
-
|
53
|
-
@trace_begin.enable(&block)
|
51
|
+
@trace_end.enable(&block)
|
54
52
|
end
|
55
53
|
|
56
54
|
# hook_builtins builds hooks for code that is built in to the Ruby standard library.
|
@@ -96,29 +94,22 @@ module AppMap
|
|
96
94
|
|
97
95
|
protected
|
98
96
|
|
99
|
-
def trace_class(trace_point)
|
100
|
-
path = trace_point.path
|
101
|
-
|
102
|
-
return if @notrace_paths.member?(path)
|
103
|
-
|
104
|
-
if config.path_enabled?(path)
|
105
|
-
location = trace_location(trace_point)
|
106
|
-
warn "Entering hook-enabled location #{location}" if Hook::LOG || Hook::LOG_HOOK
|
107
|
-
@trace_locations << location
|
108
|
-
unless @trace_end.enabled?
|
109
|
-
warn "Enabling hooking" if Hook::LOG || Hook::LOG_HOOK
|
110
|
-
@trace_end.enable
|
111
|
-
end
|
112
|
-
else
|
113
|
-
@notrace_paths << path
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
97
|
def trace_location(trace_point)
|
118
98
|
[ trace_point.path, trace_point.lineno ].join(':')
|
119
99
|
end
|
120
100
|
|
121
101
|
def trace_end(trace_point)
|
102
|
+
location = trace_location(trace_point)
|
103
|
+
warn "Class or module ends at location #{trace_location(trace_point)}" if Hook::LOG || Hook::LOG_HOOK
|
104
|
+
|
105
|
+
path = trace_point.path
|
106
|
+
enabled = !@notrace_paths.member?(path) && config.path_enabled?(path)
|
107
|
+
if !enabled
|
108
|
+
warn "Not hooking - path is not enabled" if Hook::LOG || Hook::LOG_HOOK
|
109
|
+
@notrace_paths << path
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
122
113
|
cls = trace_point.self
|
123
114
|
|
124
115
|
instance_methods = cls.public_instance_methods(false) - OBJECT_INSTANCE_METHODS
|
@@ -151,7 +142,8 @@ module AppMap
|
|
151
142
|
warn "AppMap: Examining #{hook_cls} #{method.name}" if LOG
|
152
143
|
|
153
144
|
disasm = RubyVM::InstructionSequence.disasm(method)
|
154
|
-
# Skip methods that have no instruction sequence, as they are
|
145
|
+
# Skip methods that have no instruction sequence, as they are either have no body or they are or native.
|
146
|
+
# TODO: Figure out how to tell the difference?
|
155
147
|
next unless disasm
|
156
148
|
|
157
149
|
package = config.lookup_package(hook_cls, method)
|
@@ -170,13 +162,6 @@ module AppMap
|
|
170
162
|
# uninitialized constant Faraday::Connection
|
171
163
|
warn "NameError in #{__FILE__}: #{$!.message}"
|
172
164
|
end
|
173
|
-
|
174
|
-
location = @trace_locations.pop
|
175
|
-
warn "Leaving hook-enabled location #{location}" if Hook::LOG || Hook::LOG_HOOK
|
176
|
-
if @trace_locations.empty?
|
177
|
-
warn "Disabling hooking" if Hook::LOG || Hook::LOG_HOOK
|
178
|
-
@trace_end.disable
|
179
|
-
end
|
180
165
|
end
|
181
166
|
end
|
182
167
|
end
|
data/lib/appmap/minitest.rb
CHANGED
@@ -54,15 +54,21 @@ module AppMap
|
|
54
54
|
|
55
55
|
@recordings_by_test = {}
|
56
56
|
@event_methods = Set.new
|
57
|
+
@recording_count = 0
|
57
58
|
|
58
59
|
class << self
|
59
60
|
def init
|
60
|
-
warn 'Configuring AppMap recorder for Minitest'
|
61
|
-
|
62
61
|
FileUtils.mkdir_p APPMAP_OUTPUT_DIR
|
63
62
|
end
|
64
63
|
|
64
|
+
def first_recording?
|
65
|
+
@recording_count == 0
|
66
|
+
end
|
67
|
+
|
65
68
|
def begin_test(test, name)
|
69
|
+
AppMap.info 'Configuring AppMap recorder for Minitest' if first_recording?
|
70
|
+
@recording_count += 1
|
71
|
+
|
66
72
|
@recordings_by_test[test.object_id] = Recording.new(test, name)
|
67
73
|
end
|
68
74
|
|
@@ -98,7 +104,7 @@ module AppMap
|
|
98
104
|
if exception
|
99
105
|
m[:exception] = {
|
100
106
|
class: exception.class.name,
|
101
|
-
message: exception.to_s
|
107
|
+
message: AppMap::Event::MethodEvent.display_string(exception.to_s)
|
102
108
|
}
|
103
109
|
end
|
104
110
|
end
|
data/lib/appmap/railtie.rb
CHANGED
@@ -3,6 +3,13 @@
|
|
3
3
|
module AppMap
|
4
4
|
# Railtie connects the AppMap recorder to Rails-specific features.
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
|
+
initializer 'appmap.remote_recording' do
|
7
|
+
require 'appmap/middleware/remote_recording'
|
8
|
+
Rails.application.config.middleware.insert_after \
|
9
|
+
Rails::Rack::Logger,
|
10
|
+
AppMap::Middleware::RemoteRecording
|
11
|
+
end
|
12
|
+
|
6
13
|
# appmap.subscribe subscribes to ActiveSupport Notifications so that they can be recorded as
|
7
14
|
# AppMap events.
|
8
15
|
initializer 'appmap.subscribe' do |_| # params: app
|
data/lib/appmap/rspec.rb
CHANGED
@@ -139,15 +139,21 @@ module AppMap
|
|
139
139
|
|
140
140
|
@recordings_by_example = {}
|
141
141
|
@event_methods = Set.new
|
142
|
+
@recording_count = 0
|
142
143
|
|
143
144
|
class << self
|
144
145
|
def init
|
145
|
-
warn 'Configuring AppMap recorder for RSpec'
|
146
|
-
|
147
146
|
FileUtils.mkdir_p APPMAP_OUTPUT_DIR
|
148
147
|
end
|
149
148
|
|
149
|
+
def first_recording?
|
150
|
+
@recording_count == 0
|
151
|
+
end
|
152
|
+
|
150
153
|
def begin_spec(example)
|
154
|
+
AppMap.info 'Configuring AppMap recorder for RSpec' if first_recording?
|
155
|
+
@recording_count += 1
|
156
|
+
|
151
157
|
@recordings_by_example[example.object_id] = Recording.new(example)
|
152
158
|
end
|
153
159
|
|
@@ -183,7 +189,7 @@ module AppMap
|
|
183
189
|
if exception
|
184
190
|
m[:exception] = {
|
185
191
|
class: exception.class.name,
|
186
|
-
message: exception.to_s
|
192
|
+
message: AppMap::Event::MethodEvent.display_string(exception.to_s)
|
187
193
|
}
|
188
194
|
end
|
189
195
|
end
|
data/lib/appmap/util.rb
CHANGED
@@ -1,7 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'bundler'
|
4
|
+
|
3
5
|
module AppMap
|
4
6
|
module Util
|
7
|
+
# https://wynnnetherland.com/journal/a-stylesheet-author-s-guide-to-terminal-colors/
|
8
|
+
# Embed in a String to clear all previous ANSI sequences.
|
9
|
+
CLEAR = "\e[0m"
|
10
|
+
BOLD = "\e[1m"
|
11
|
+
|
12
|
+
# Colors
|
13
|
+
BLACK = "\e[30m"
|
14
|
+
RED = "\e[31m"
|
15
|
+
GREEN = "\e[32m"
|
16
|
+
YELLOW = "\e[33m"
|
17
|
+
BLUE = "\e[34m"
|
18
|
+
MAGENTA = "\e[35m"
|
19
|
+
CYAN = "\e[36m"
|
20
|
+
WHITE = "\e[37m"
|
21
|
+
|
5
22
|
class << self
|
6
23
|
# scenario_filename builds a suitable file name from a scenario name.
|
7
24
|
# Special characters are removed, and the file name is truncated to fit within
|
@@ -94,7 +111,7 @@ module AppMap
|
|
94
111
|
end
|
95
112
|
|
96
113
|
def normalize_path(path)
|
97
|
-
if path.index(Dir.pwd) == 0
|
114
|
+
if path.index(Dir.pwd) == 0 && !path.index(Bundler.bundle_path.to_s)
|
98
115
|
path[Dir.pwd.length + 1..-1]
|
99
116
|
else
|
100
117
|
path
|
@@ -126,6 +143,12 @@ module AppMap
|
|
126
143
|
FileUtils.mv tempfile.path, filename
|
127
144
|
end
|
128
145
|
end
|
146
|
+
|
147
|
+
def color(text, color, bold: false)
|
148
|
+
color = Util.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
149
|
+
bold = bold ? BOLD : ""
|
150
|
+
"#{bold}#{color}#{text}#{CLEAR}"
|
151
|
+
end
|
129
152
|
end
|
130
153
|
end
|
131
154
|
end
|
data/lib/appmap/version.rb
CHANGED
@@ -1,9 +1,30 @@
|
|
1
1
|
require 'rails_spec_helper'
|
2
2
|
|
3
3
|
describe 'Rails' do
|
4
|
+
shared_context 'rails integration test setup' do
|
5
|
+
def tmpdir
|
6
|
+
'tmp/spec/AbstractControllerBase'
|
7
|
+
end
|
8
|
+
|
9
|
+
unless use_existing_data?
|
10
|
+
before(:all) do
|
11
|
+
FileUtils.rm_rf tmpdir
|
12
|
+
FileUtils.mkdir_p tmpdir
|
13
|
+
run_spec 'spec/controllers/users_controller_spec.rb'
|
14
|
+
run_spec 'spec/controllers/users_controller_api_spec.rb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
|
19
|
+
let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
|
20
|
+
let(:appmap) { JSON.parse File.read(appmap_json_path) }
|
21
|
+
let(:events) { appmap['events'] }
|
22
|
+
end
|
23
|
+
|
4
24
|
%w[5 6].each do |rails_major_version| # rubocop:disable Metrics/BlockLength
|
5
25
|
context "#{rails_major_version}" do
|
6
26
|
include_context 'Rails app pg database', "spec/fixtures/rails#{rails_major_version}_users_app" unless use_existing_data?
|
27
|
+
include_context 'rails integration test setup'
|
7
28
|
|
8
29
|
def run_spec(spec_name)
|
9
30
|
cmd = <<~CMD.gsub "\n", ' '
|
@@ -13,24 +34,6 @@ describe 'Rails' do
|
|
13
34
|
run_cmd cmd, chdir: fixture_dir
|
14
35
|
end
|
15
36
|
|
16
|
-
def tmpdir
|
17
|
-
'tmp/spec/AbstractControllerBase'
|
18
|
-
end
|
19
|
-
|
20
|
-
unless use_existing_data?
|
21
|
-
before(:all) do
|
22
|
-
FileUtils.rm_rf tmpdir
|
23
|
-
FileUtils.mkdir_p tmpdir
|
24
|
-
run_spec 'spec/controllers/users_controller_spec.rb'
|
25
|
-
run_spec 'spec/controllers/users_controller_api_spec.rb'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
|
30
|
-
let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
|
31
|
-
let(:appmap) { JSON.parse File.read(appmap_json_path) }
|
32
|
-
let(:events) { appmap['events'] }
|
33
|
-
|
34
37
|
describe 'an API route' do
|
35
38
|
describe 'creating an object' do
|
36
39
|
let(:appmap_json_file) do
|
@@ -253,4 +256,40 @@ describe 'Rails' do
|
|
253
256
|
end
|
254
257
|
end
|
255
258
|
end
|
259
|
+
|
260
|
+
describe 'with default appmap.yml' do
|
261
|
+
include_context 'Rails app pg database', "spec/fixtures/rails5_users_app" unless use_existing_data?
|
262
|
+
include_context 'rails integration test setup'
|
263
|
+
|
264
|
+
def run_spec(spec_name)
|
265
|
+
cmd = <<~CMD.gsub "\n", ' '
|
266
|
+
docker-compose run --rm -e RAILS_ENV=test -e APPMAP=true -e APPMAP_CONFIG_FILE=no/such/file
|
267
|
+
-v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec #{spec_name}
|
268
|
+
CMD
|
269
|
+
run_cmd cmd, chdir: fixture_dir
|
270
|
+
end
|
271
|
+
|
272
|
+
let(:appmap_json_file) do
|
273
|
+
'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json'
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'http_server_request is recorded' do
|
277
|
+
expect(events).to include(
|
278
|
+
hash_including(
|
279
|
+
'http_server_request' => hash_including(
|
280
|
+
'request_method' => 'POST',
|
281
|
+
'path_info' => '/api/users'
|
282
|
+
)
|
283
|
+
)
|
284
|
+
)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'controller method is recorded' do
|
288
|
+
expect(events).to include hash_including(
|
289
|
+
'defined_class' => 'Api::UsersController',
|
290
|
+
'method_id' => 'build_user',
|
291
|
+
'path' => 'app/controllers/api/users_controller.rb',
|
292
|
+
)
|
293
|
+
end
|
294
|
+
end
|
256
295
|
end
|