appmap 0.39.1 → 0.42.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/CONTRIBUTING.md +22 -0
  4. data/README.md +105 -50
  5. data/lib/appmap.rb +5 -0
  6. data/lib/appmap/class_map.rb +25 -8
  7. data/lib/appmap/command/record.rb +1 -1
  8. data/lib/appmap/config.rb +48 -28
  9. data/lib/appmap/event.rb +14 -4
  10. data/lib/appmap/hook.rb +7 -0
  11. data/lib/appmap/hook/method.rb +1 -1
  12. data/lib/appmap/middleware/remote_recording.rb +1 -1
  13. data/lib/appmap/minitest.rb +17 -14
  14. data/lib/appmap/rails/request_handler.rb +8 -3
  15. data/lib/appmap/railtie.rb +1 -5
  16. data/lib/appmap/rspec.rb +12 -78
  17. data/lib/appmap/version.rb +1 -1
  18. data/spec/abstract_controller_base_spec.rb +2 -2
  19. data/spec/config_spec.rb +1 -0
  20. data/spec/fixtures/hook/exclude.rb +15 -0
  21. data/spec/fixtures/hook/labels.rb +6 -0
  22. data/spec/fixtures/rails5_users_app/Gemfile +2 -3
  23. data/spec/fixtures/rails5_users_app/appmap.yml +4 -1
  24. data/spec/fixtures/rails5_users_app/config/application.rb +2 -0
  25. data/spec/fixtures/rails5_users_app/docker-compose.yml +3 -0
  26. data/spec/fixtures/rails5_users_app/spec/controllers/users_controller_api_spec.rb +3 -3
  27. data/spec/fixtures/rails5_users_app/spec/models/user_spec.rb +2 -12
  28. data/spec/fixtures/rails6_users_app/Gemfile +2 -3
  29. data/spec/fixtures/rails6_users_app/appmap.yml +4 -1
  30. data/spec/fixtures/rails6_users_app/config/application.rb +2 -0
  31. data/spec/fixtures/rails6_users_app/docker-compose.yml +3 -0
  32. data/spec/fixtures/rails6_users_app/spec/controllers/users_controller_api_spec.rb +3 -3
  33. data/spec/fixtures/rails6_users_app/spec/models/user_spec.rb +2 -12
  34. data/spec/hook_spec.rb +37 -1
  35. data/spec/record_sql_rails_pg_spec.rb +1 -1
  36. data/spec/spec_helper.rb +1 -0
  37. data/test/fixtures/gem_test/appmap.yml +1 -1
  38. data/test/fixtures/gem_test/test/parser_test.rb +12 -0
  39. data/test/fixtures/rspec_recorder/spec/decorated_hello_spec.rb +3 -3
  40. data/test/fixtures/rspec_recorder/spec/plain_hello_spec.rb +1 -1
  41. data/test/gem_test.rb +4 -4
  42. data/test/minitest_test.rb +1 -2
  43. data/test/rspec_test.rb +1 -7
  44. metadata +6 -4
  45. data/spec/rspec_feature_metadata_spec.rb +0 -31
  46. data/test/fixtures/gem_test/test/to_param_test.rb +0 -14
@@ -1,4 +1,7 @@
1
1
  name: rails5_users_app
2
2
  packages:
3
- - path: app
3
+ - path: app/models
4
+ labels: [ mvc.model ]
5
+ - path: app/controllers
6
+ labels: [ mvc.controller ]
4
7
  - gem: sequel
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -19,6 +19,9 @@ services:
19
19
  environment:
20
20
  RAILS_ENV:
21
21
  ORM_MODULE:
22
+ PGHOST: pg
23
+ PGPORT: '5432'
24
+ DATABASE_URL: postgres://postgres@pg
22
25
  APPMAP:
23
26
  volumes:
24
27
  - .:/src/app
@@ -1,8 +1,8 @@
1
1
  require 'rails_helper'
2
2
  require 'rack/test'
3
3
 
4
- RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller, appmap: true do
5
- describe 'POST /api/users', feature: 'Create a user' do
4
+ RSpec.describe Api::UsersController, type: :controller do
5
+ describe 'POST /api/users' do
6
6
  describe 'with required parameters' do
7
7
  it 'creates a user' do
8
8
  post :create, params: { login: 'alice', password: 'foobar' }
@@ -16,7 +16,7 @@ RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller,
16
16
  end
17
17
  end
18
18
  end
19
- describe 'GET /api/users', feature: 'List users' do
19
+ describe 'GET /api/users' do
20
20
  before do
21
21
  post :create, params: { login: 'alice' }
22
22
  end
@@ -1,6 +1,6 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe User, feature_group: 'User', appmap: true do
3
+ describe User do
4
4
  # TODO: appmap/rspec doesn't handle shared_examples_for 100% correctly yet.
5
5
  # In my tests, only one of these two tests will be emitted as an appmap.
6
6
  shared_examples_for 'creates the user' do |username|
@@ -11,17 +11,7 @@ describe User, feature_group: 'User', appmap: true do
11
11
  end
12
12
  end
13
13
 
14
- describe 'creation', feature: 'Create a user' do
15
- context 'using shared_examples_for' do
16
- # AppMap.
17
- # context "with username 'alice'" do
18
- # it_should_behave_like 'creates the user', 'alice'
19
- # end
20
- # context "with username 'bob'" do
21
- # it_should_behave_like 'creates the user', 'bob'
22
- # end
23
- end
24
-
14
+ describe 'creation' do
25
15
  # So, instead of shared_examples_for, let's go with a simple method
26
16
  # containing the assertions. The method can be called from within an example.
27
17
  def save_and_verify
@@ -34,11 +34,10 @@ appmap_options = \
34
34
  { path: appmap_path }
35
35
  else
36
36
  {}
37
- end.merge(require: %w[appmap appmap/railtie])
38
-
39
- gem 'appmap', appmap_options
37
+ end.merge(require: %w[appmap])
40
38
 
41
39
  group :development, :test do
40
+ gem 'appmap', appmap_options
42
41
  gem 'cucumber-rails', require: false
43
42
  gem 'rspec-rails'
44
43
  # Required for Sequel, since without ActiveRecord, the Rails transactional fixture support
@@ -1,5 +1,8 @@
1
1
  name: rails6_users_app
2
2
  packages:
3
- - path: app
3
+ - path: app/models
4
+ labels: [ mvc.model ]
5
+ - path: app/controllers
6
+ labels: [ mvc.controller ]
4
7
  - gem: sequel
5
8
 
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -19,6 +19,9 @@ services:
19
19
  environment:
20
20
  RAILS_ENV:
21
21
  ORM_MODULE:
22
+ PGHOST: pg
23
+ PGPORT: '5432'
24
+ DATABASE_URL: postgres://postgres@pg
22
25
  APPMAP:
23
26
  volumes:
24
27
  - .:/src/app
@@ -1,8 +1,8 @@
1
1
  require 'rails_helper'
2
2
  require 'rack/test'
3
3
 
4
- RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller, appmap: true do
5
- describe 'POST /api/users', feature: 'Create a user' do
4
+ RSpec.describe Api::UsersController, type: :controller do
5
+ describe 'POST /api/users' do
6
6
  describe 'with required parameters' do
7
7
  it 'creates a user' do
8
8
  post :create, params: { login: 'alice', password: 'foobar' }
@@ -16,7 +16,7 @@ RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller,
16
16
  end
17
17
  end
18
18
  end
19
- describe 'GET /api/users', feature: 'List users' do
19
+ describe 'GET /api/users' do
20
20
  before do
21
21
  post :create, params: { login: 'alice' }
22
22
  end
@@ -1,6 +1,6 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe User, feature_group: 'User', appmap: true do
3
+ describe User do
4
4
  # TODO: appmap/rspec doesn't handle shared_examples_for 100% correctly yet.
5
5
  # In my tests, only one of these two tests will be emitted as an appmap.
6
6
  shared_examples_for 'creates the user' do |username|
@@ -11,17 +11,7 @@ describe User, feature_group: 'User', appmap: true do
11
11
  end
12
12
  end
13
13
 
14
- describe 'creation', feature: 'Create a user' do
15
- context 'using shared_examples_for' do
16
- # AppMap.
17
- # context "with username 'alice'" do
18
- # it_should_behave_like 'creates the user', 'alice'
19
- # end
20
- # context "with username 'bob'" do
21
- # it_should_behave_like 'creates the user', 'bob'
22
- # end
23
- end
24
-
14
+ describe 'creation' do
25
15
  # So, instead of shared_examples_for, let's go with a simple method
26
16
  # containing the assertions. The method can be called from within an example.
27
17
  def save_and_verify
data/spec/hook_spec.rb CHANGED
@@ -61,6 +61,42 @@ describe 'AppMap class Hooking', docker: false do
61
61
  AppMap.configuration = nil
62
62
  end
63
63
 
64
+ it 'excludes named classes and methods' do
65
+ load 'spec/fixtures/hook/exclude.rb'
66
+ package = AppMap::Config::Package.build_from_path('spec/fixtures/hook/exclude.rb')
67
+ config = AppMap::Config.new('hook_spec', [ package ], %w[ExcludeTest])
68
+ AppMap.configuration = config
69
+
70
+ expect(config.never_hook?(ExcludeTest.new.method(:instance_method))).to be_truthy
71
+ expect(config.never_hook?(ExcludeTest.method(:cls_method))).to be_truthy
72
+ end
73
+
74
+ it 'parses labels from comments' do
75
+ _, tracer = invoke_test_file 'spec/fixtures/hook/labels.rb' do
76
+ ClassWithLabel.new.fn_with_label
77
+ end
78
+ class_map = AppMap.class_map(tracer.event_methods).to_yaml
79
+ expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
80
+ ---
81
+ - :name: spec/fixtures/hook/labels.rb
82
+ :type: package
83
+ :children:
84
+ - :name: ClassWithLabel
85
+ :type: class
86
+ :children:
87
+ - :name: fn_with_label
88
+ :type: function
89
+ :location: spec/fixtures/hook/labels.rb:4
90
+ :static: false
91
+ :labels:
92
+ - has-fn-label
93
+ :comment: "# @label has-fn-label\\n"
94
+ :source: |2
95
+ def fn_with_label
96
+ end
97
+ YAML
98
+ end
99
+
64
100
  it 'hooks an instance method that takes no arguments' do
65
101
  events_yaml = <<~YAML
66
102
  ---
@@ -801,7 +837,7 @@ describe 'AppMap class Hooking', docker: false do
801
837
  entry = cm[1][:children][0][:children][0][:children][0]
802
838
  # Sanity check, make sure we got the right one
803
839
  expect(entry[:name]).to eq('secure_compare')
804
- expect(entry[:labels]).to eq(%w[security crypto])
840
+ expect(entry[:labels]).to eq(%w[provider.secure_compare])
805
841
  end
806
842
  end
807
843
 
@@ -5,7 +5,7 @@ describe 'SQL events' do
5
5
  around(:each) do |example|
6
6
  FileUtils.rm_rf tmpdir
7
7
  FileUtils.mkdir_p tmpdir
8
- cmd = "docker-compose run --rm -e ORM_MODULE=#{orm_module} -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:#{test_line_number}"
8
+ cmd = "docker-compose run --rm -e ORM_MODULE=#{orm_module} -e RAILS_ENV=test -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:#{test_line_number}"
9
9
  run_cmd cmd, chdir: fixture_dir
10
10
 
11
11
  example.run
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ require 'net/http'
3
3
  require 'json'
4
4
  require 'yaml'
5
5
  require 'English'
6
+ require 'byebug'
6
7
  require 'webdrivers/chromedriver'
7
8
 
8
9
  # Disable default initialization of AppMap
@@ -1,3 +1,3 @@
1
1
  name: gem_test
2
2
  packages:
3
- - gem: activesupport
3
+ - gem: parser
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'appmap/minitest'
5
+ require 'minitest/autorun'
6
+ require 'parser/current'
7
+
8
+ class ParserTest < ::Minitest::Test
9
+ def test_parser
10
+ Parser::CurrentRuby.parse(File.read(__FILE__))
11
+ end
12
+ end
@@ -2,7 +2,7 @@ require 'rspec'
2
2
  require 'appmap/rspec'
3
3
  require 'hello'
4
4
 
5
- describe Hello, feature_group: 'Saying hello' do
5
+ describe Hello do
6
6
  before do
7
7
  # Trick appmap-ruby into thinking we're a Rails app.
8
8
  stub_const('Rails', double('rails', version: 'fake.0'))
@@ -11,11 +11,11 @@ describe Hello, feature_group: 'Saying hello' do
11
11
  # The order of these examples is important. The tests check the
12
12
  # appmap for 'says hello', and we want another example to get run
13
13
  # before it.
14
- it 'does not say goodbye', feature: 'Speak hello', appmap: true do
14
+ it 'does not say goodbye' do
15
15
  expect(Hello.new.say_hello).not_to eq('Goodbye!')
16
16
  end
17
17
 
18
- it 'says hello', feature: 'Speak hello', appmap: true do
18
+ it 'says hello' do
19
19
  expect(Hello.new.say_hello).to eq('Hello!')
20
20
  end
21
21
  end
@@ -2,7 +2,7 @@ require 'rspec'
2
2
  require 'appmap/rspec'
3
3
  require 'hello'
4
4
 
5
- describe Hello, appmap: true do
5
+ describe Hello do
6
6
  it 'says hello' do
7
7
  expect(Hello.new.say_hello).to eq('Hello!')
8
8
  end
data/test/gem_test.rb CHANGED
@@ -19,14 +19,14 @@ class MinitestTest < Minitest::Test
19
19
  end
20
20
 
21
21
  def test_record_gem
22
- perform_gem_test 'to_param' do
23
- appmap_file = 'tmp/appmap/minitest/To_param_to_param.appmap.json'
22
+ perform_gem_test 'parser' do
23
+ appmap_file = 'tmp/appmap/minitest/Parser_parser.appmap.json'
24
24
  appmap = JSON.parse(File.read(appmap_file))
25
25
  events = appmap['events']
26
26
  assert_equal 2, events.size
27
27
  assert_equal 'call', events.first['event']
28
- assert_equal 'to_param', events.first['method_id']
29
- assert_equal "#{Gem.loaded_specs['activesupport'].gem_dir}/lib/active_support/core_ext/object/to_query.rb", events.first['path']
28
+ assert_equal 'default_parser', events.first['method_id']
29
+ assert_equal "#{Gem.loaded_specs['parser'].gem_dir}/lib/parser/base.rb", events.first['path']
30
30
  assert_equal 'return', events.second['event']
31
31
  assert_equal 1, events.second['parent_id']
32
32
  end
@@ -30,9 +30,8 @@ class MinitestTest < Minitest::Test
30
30
  assert_equal 'minitest_recorder', metadata['app']
31
31
  assert_equal 'minitest', metadata['recorder']['name']
32
32
  assert_equal 'ruby', metadata['language']['name']
33
- assert_equal 'Hello', metadata['feature_group']
34
- assert_equal 'hello', metadata['feature']
35
33
  assert_equal 'Hello hello', metadata['name']
34
+ assert_equal 'test/hello_test.rb:9', metadata['source_location']
36
35
  end
37
36
  end
38
37
  end
data/test/rspec_test.rb CHANGED
@@ -28,8 +28,6 @@ class RSpecTest < Minitest::Test
28
28
  assert_includes appmap.keys, 'metadata'
29
29
  metadata = appmap['metadata']
30
30
  assert_equal 'Inventory', metadata['name']
31
- assert_includes metadata.keys, 'labels'
32
- assert_equal metadata['labels'], %w[inventory]
33
31
  end
34
32
  end
35
33
 
@@ -42,9 +40,8 @@ class RSpecTest < Minitest::Test
42
40
  assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
43
41
  assert_includes appmap.keys, 'metadata'
44
42
  metadata = appmap['metadata']
45
- assert_equal 'Saying hello', metadata['feature_group']
46
- assert_equal 'Speak hello', metadata['feature']
47
43
  assert_equal 'Hello says hello', metadata['name']
44
+ assert_equal 'spec/decorated_hello_spec.rb', metadata['source_location']
48
45
  assert_includes metadata.keys, 'client'
49
46
  assert_equal({ name: 'appmap', url: AppMap::URL, version: AppMap::VERSION }.stringify_keys, metadata['client'])
50
47
  assert_includes metadata.keys, 'recorder'
@@ -63,8 +60,6 @@ class RSpecTest < Minitest::Test
63
60
  appmap = JSON.parse(File.read(appmap_file))
64
61
  assert_includes appmap.keys, 'metadata'
65
62
  metadata = appmap['metadata']
66
- assert_equal 'Hello', metadata['feature_group']
67
- assert_equal 'Hello', metadata['feature']
68
63
  assert_equal 'Hello says hello', metadata['name']
69
64
  end
70
65
  end
@@ -76,7 +71,6 @@ class RSpecTest < Minitest::Test
76
71
  appmap = JSON.parse(File.read(appmap_file))
77
72
  assert_includes appmap.keys, 'metadata'
78
73
  metadata = appmap['metadata']
79
- assert_equal %w[hello speak], metadata['labels'].sort
80
74
  end
81
75
  end
82
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.1
4
+ version: 0.42.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-22 00:00:00.000000000 Z
11
+ date: 2021-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -319,6 +319,7 @@ files:
319
319
  - ".rubocop.yml"
320
320
  - ".travis.yml"
321
321
  - CHANGELOG.md
322
+ - CONTRIBUTING.md
322
323
  - Dockerfile.appmap
323
324
  - Gemfile
324
325
  - LICENSE.txt
@@ -385,7 +386,9 @@ files:
385
386
  - spec/fixtures/hook/compare.rb
386
387
  - spec/fixtures/hook/constructor.rb
387
388
  - spec/fixtures/hook/exception_method.rb
389
+ - spec/fixtures/hook/exclude.rb
388
390
  - spec/fixtures/hook/instance_method.rb
391
+ - spec/fixtures/hook/labels.rb
389
392
  - spec/fixtures/hook/singleton_method.rb
390
393
  - spec/fixtures/rack_users_app/.dockerignore
391
394
  - spec/fixtures/rack_users_app/.gitignore
@@ -545,7 +548,6 @@ files:
545
548
  - spec/railtie_spec.rb
546
549
  - spec/record_sql_rails_pg_spec.rb
547
550
  - spec/remote_recording_spec.rb
548
- - spec/rspec_feature_metadata_spec.rb
549
551
  - spec/spec_helper.rb
550
552
  - spec/util_spec.rb
551
553
  - test/cli_test.rb
@@ -570,7 +572,7 @@ files:
570
572
  - test/fixtures/cucumber_recorder/lib/hello.rb
571
573
  - test/fixtures/gem_test/Gemfile
572
574
  - test/fixtures/gem_test/appmap.yml
573
- - test/fixtures/gem_test/test/to_param_test.rb
575
+ - test/fixtures/gem_test/test/parser_test.rb
574
576
  - test/fixtures/minitest_recorder/Gemfile
575
577
  - test/fixtures/minitest_recorder/appmap.yml
576
578
  - test/fixtures/minitest_recorder/lib/hello.rb
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails_spec_helper'
4
-
5
- describe 'RSpec feature and feature group metadata' do
6
- include_examples 'Rails app pg database', 'spec/fixtures/rails5_users_app' do
7
- around(:each) do |example|
8
- FileUtils.rm_rf tmpdir
9
- FileUtils.mkdir_p tmpdir
10
- cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path(tmpdir).shellescape}:/app/tmp app ./bin/rspec spec/models/user_spec.rb"
11
- run_cmd cmd, chdir: fixture_dir
12
-
13
- example.run
14
- end
15
-
16
- let(:tmpdir) { 'tmp/spec/RSpec feature and feature group metadata' }
17
- let(:appmap_json) { File.join(tmpdir, %(appmap/rspec/User_creation_creates_charles.appmap.json)) }
18
-
19
- describe do
20
- it 'are recorded in the appmap' do
21
- expect(File).to exist(appmap_json)
22
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
23
-
24
- expect(appmap).to include(<<-METADATA.strip)
25
- feature: Create a user
26
- feature_group: User
27
- METADATA
28
- end
29
- end
30
- end
31
- end