appmap 0.27.0 → 0.28.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +120 -31
  5. data/exe/appmap +3 -1
  6. data/lib/appmap.rb +40 -35
  7. data/lib/appmap/command/record.rb +2 -61
  8. data/lib/appmap/cucumber.rb +89 -0
  9. data/lib/appmap/hook.rb +6 -1
  10. data/lib/appmap/metadata.rb +62 -0
  11. data/lib/appmap/middleware/remote_recording.rb +2 -6
  12. data/lib/appmap/railtie.rb +2 -2
  13. data/lib/appmap/rspec.rb +8 -36
  14. data/lib/appmap/trace.rb +8 -8
  15. data/lib/appmap/util.rb +40 -0
  16. data/lib/appmap/version.rb +1 -1
  17. data/spec/fixtures/rails_users_app/Gemfile +1 -0
  18. data/spec/fixtures/rails_users_app/features/api_users.feature +13 -0
  19. data/spec/fixtures/rails_users_app/features/support/env.rb +4 -0
  20. data/spec/fixtures/rails_users_app/features/support/hooks.rb +11 -0
  21. data/spec/fixtures/rails_users_app/features/support/steps.rb +18 -0
  22. data/spec/hook_spec.rb +8 -2
  23. data/spec/rails_spec_helper.rb +2 -0
  24. data/spec/rspec_feature_metadata_spec.rb +2 -0
  25. data/spec/spec_helper.rb +4 -0
  26. data/spec/util_spec.rb +21 -0
  27. data/test/cucumber_test.rb +72 -0
  28. data/test/fixtures/cucumber4_recorder/Gemfile +5 -0
  29. data/test/fixtures/cucumber4_recorder/appmap.yml +3 -0
  30. data/test/fixtures/cucumber4_recorder/features/say_hello.feature +5 -0
  31. data/test/fixtures/cucumber4_recorder/features/support/env.rb +5 -0
  32. data/test/fixtures/cucumber4_recorder/features/support/hooks.rb +11 -0
  33. data/test/fixtures/cucumber4_recorder/features/support/steps.rb +9 -0
  34. data/test/fixtures/cucumber4_recorder/lib/hello.rb +7 -0
  35. data/test/fixtures/cucumber_recorder/Gemfile +5 -0
  36. data/test/fixtures/cucumber_recorder/appmap.yml +3 -0
  37. data/test/fixtures/cucumber_recorder/features/say_hello.feature +5 -0
  38. data/test/fixtures/cucumber_recorder/features/support/env.rb +5 -0
  39. data/test/fixtures/cucumber_recorder/features/support/hooks.rb +11 -0
  40. data/test/fixtures/cucumber_recorder/features/support/steps.rb +9 -0
  41. data/test/fixtures/cucumber_recorder/lib/hello.rb +7 -0
  42. metadata +26 -2
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ When 'I create a user' do
4
+ @response = post '/api/users', login: 'alice'
5
+ end
6
+
7
+ Then(/the response status should be (\d+)/) do |status|
8
+ expect(@response.status).to eq(status.to_i)
9
+ end
10
+
11
+ When 'I list the users' do
12
+ @response = get '/api/users'
13
+ @users = JSON.parse(@response.body)
14
+ end
15
+
16
+ Then 'the response should include the user' do
17
+ expect(@users.map { |u| u['login'] }).to include('alice')
18
+ end
@@ -31,8 +31,10 @@ describe 'AppMap class Hooking' do
31
31
  end
32
32
 
33
33
  def invoke_test_file(file, &block)
34
+ AppMap.configuration = nil
34
35
  package = AppMap::Hook::Package.new(file, [])
35
36
  config = AppMap::Hook::Config.new('hook_spec', [ package ])
37
+ AppMap.configuration = config
36
38
  AppMap::Hook.hook(config)
37
39
 
38
40
  tracer = AppMap.tracing.trace
@@ -55,6 +57,10 @@ describe 'AppMap class Hooking' do
55
57
  [ config, tracer ]
56
58
  end
57
59
 
60
+ after do
61
+ AppMap.configuration = nil
62
+ end
63
+
58
64
  it 'hooks an instance method that takes no arguments' do
59
65
  events_yaml = <<~YAML
60
66
  ---
@@ -90,10 +96,10 @@ describe 'AppMap class Hooking' do
90
96
  end
91
97
 
92
98
  it 'builds a class map of invoked methods' do
93
- config, tracer = invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
99
+ _, tracer = invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
94
100
  InstanceMethod.new.say_default
95
101
  end
96
- class_map = AppMap.class_map(config, tracer.event_methods).to_yaml
102
+ class_map = AppMap.class_map(tracer.event_methods).to_yaml
97
103
  expect(Diffy::Diff.new(class_map, <<~YAML).to_s).to eq('')
98
104
  ---
99
105
  - :name: spec/fixtures/hook/instance_method.rb
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'open3'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails_spec_helper'
2
4
 
3
5
  describe 'RSpec feature and feature group metadata' do
@@ -4,6 +4,10 @@ require 'json'
4
4
  require 'yaml'
5
5
  require 'English'
6
6
  require 'webdrivers/chromedriver'
7
+
8
+ # Disable default initialization of AppMap
9
+ ENV['APPMAP_INITIALIZE'] = 'false'
10
+
7
11
  require 'appmap'
8
12
 
9
13
  RSpec.configure do |config|
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'appmap/util'
5
+
6
+ describe AppMap::Util do
7
+ let(:subject) { AppMap::Util.method(:scenario_filename) }
8
+ describe 'scenario_filename' do
9
+ it 'leaves short names alone' do
10
+ expect(subject.call('foobar')).to eq('foobar.appmap.json')
11
+ end
12
+ it 'has a customizable suffix' do
13
+ expect(subject.call('foobar', extension: '.json')).to eq('foobar.json')
14
+ end
15
+ it 'limits the filename length' do
16
+ fname = (0...104).map { |i| ((i % 26) + 97).chr }.join
17
+
18
+ expect(subject.call(fname, max_length: 50)).to eq('abcdefghijklmno-RAd_SFbH1sUZ_OXfwPsfzw.appmap.json')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'test_helper'
5
+ require 'English'
6
+
7
+ class CucumberTest < Minitest::Test
8
+ def perform_test(dir)
9
+ Bundler.with_clean_env do
10
+ Dir.chdir "test/fixtures/#{dir}" do
11
+ FileUtils.rm_rf 'tmp'
12
+ system 'bundle config --local local.appmap ../../..'
13
+ system 'bundle'
14
+ system({ 'APPMAP' => 'true' }, %(bundle exec cucumber))
15
+
16
+ yield
17
+ end
18
+ end
19
+ end
20
+
21
+ def test_cucumber
22
+ perform_test 'cucumber_recorder' do
23
+ appmap_file = 'tmp/appmap/cucumber/Say_hello.appmap.json'
24
+
25
+ assert File.file?(appmap_file),
26
+ %(appmap output file does not exist in #{Dir.new('tmp/appmap/cucumber').entries.join(', ')})
27
+ appmap = JSON.parse(File.read(appmap_file))
28
+ assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
29
+ assert_includes appmap.keys, 'metadata'
30
+ metadata = appmap['metadata']
31
+
32
+ assert_equal 'say_hello', metadata['feature_group']
33
+ assert_equal 'I can say hello', metadata['feature']
34
+ assert_equal 'Say hello', metadata['name']
35
+ assert_includes metadata.keys, 'client'
36
+ assert_equal({ name: 'appmap', url: AppMap::URL, version: AppMap::VERSION }.stringify_keys, metadata['client'])
37
+ assert_includes metadata.keys, 'recorder'
38
+ assert_equal({ name: 'cucumber' }.stringify_keys, metadata['recorder'])
39
+
40
+ assert_includes metadata.keys, 'frameworks'
41
+ cucumber = metadata['frameworks'].select {|f| f['name'] == 'cucumber'}
42
+ assert_equal 1, cucumber.count
43
+ end
44
+ end
45
+
46
+ def test_cucumber4
47
+ perform_test 'cucumber4_recorder' do
48
+ appmap_file = 'tmp/appmap/cucumber/Say_hello.appmap.json'
49
+
50
+ assert File.file?(appmap_file),
51
+ %(appmap output file does not exist in #{Dir.new('tmp/appmap/cucumber').entries.join(', ')})
52
+ appmap = JSON.parse(File.read(appmap_file))
53
+ assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
54
+ assert_includes appmap.keys, 'metadata'
55
+ metadata = appmap['metadata']
56
+
57
+ assert_equal 'say_hello', metadata['feature_group']
58
+ # In cucumber4, there's no access to the feature name from within the executing scenario
59
+ # (as far as I can tell).
60
+ assert_equal 'Say hello', metadata['feature']
61
+ assert_equal 'Say hello', metadata['name']
62
+ assert_includes metadata.keys, 'client'
63
+ assert_equal({ name: 'appmap', url: AppMap::URL, version: AppMap::VERSION }.stringify_keys, metadata['client'])
64
+ assert_includes metadata.keys, 'recorder'
65
+ assert_equal({ name: 'cucumber' }.stringify_keys, metadata['recorder'])
66
+
67
+ assert_includes metadata.keys, 'frameworks'
68
+ cucumber = metadata['frameworks'].select {|f| f['name'] == 'cucumber'}
69
+ assert_equal 1, cucumber.count
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'appmap', git: 'applandinc/appmap-ruby', branch: `git rev-parse --abbrev-ref HEAD`.strip
4
+ gem 'byebug'
5
+ gem 'cucumber', '>= 4'
@@ -0,0 +1,3 @@
1
+ name: cucumber_recorder
2
+ packages:
3
+ - path: lib
@@ -0,0 +1,5 @@
1
+ Feature: I can say hello
2
+
3
+ Scenario: Say hello
4
+ When I say hello
5
+ Then the message is hello
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber'
4
+ require 'appmap/cucumber'
5
+ require File.join(__dir__, '../../lib/hello')
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap'
4
+
5
+ Around('not @appmap-disable') do |scenario, block|
6
+ appmap = AppMap.record do
7
+ block.call
8
+ end
9
+
10
+ AppMap::Cucumber.write_scenario(scenario, appmap)
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ When('I say hello') do
4
+ @message = Hello.new.say_hello
5
+ end
6
+
7
+ Then('the message is hello') do
8
+ raise 'Wrong message!' unless @message == 'Hello!'
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hello
4
+ def say_hello
5
+ 'Hello!'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'appmap', git: 'applandinc/appmap-ruby', branch: `git rev-parse --abbrev-ref HEAD`.strip
4
+ gem 'byebug'
5
+ gem 'cucumber', '< 4'
@@ -0,0 +1,3 @@
1
+ name: cucumber_recorder
2
+ packages:
3
+ - path: lib
@@ -0,0 +1,5 @@
1
+ Feature: I can say hello
2
+
3
+ Scenario: Say hello
4
+ When I say hello
5
+ Then the message is hello
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber'
4
+ require 'appmap/cucumber'
5
+ require File.join(__dir__, '../../lib/hello')
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap'
4
+
5
+ Around('not @appmap-disable') do |scenario, block|
6
+ appmap = AppMap.record do
7
+ block.call
8
+ end
9
+
10
+ AppMap::Cucumber.write_scenario(scenario, appmap)
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ When('I say hello') do
4
+ @message = Hello.new.say_hello
5
+ end
6
+
7
+ Then('the message is hello') do
8
+ raise 'Wrong message!' unless @message == 'Hello!'
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hello
4
+ def say_hello
5
+ 'Hello!'
6
+ end
7
+ 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.27.0
4
+ version: 0.28.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: 2020-06-17 00:00:00.000000000 Z
11
+ date: 2020-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -269,14 +269,17 @@ files:
269
269
  - lib/appmap/class_map.rb
270
270
  - lib/appmap/command/record.rb
271
271
  - lib/appmap/command/stats.rb
272
+ - lib/appmap/cucumber.rb
272
273
  - lib/appmap/event.rb
273
274
  - lib/appmap/hook.rb
275
+ - lib/appmap/metadata.rb
274
276
  - lib/appmap/middleware/remote_recording.rb
275
277
  - lib/appmap/rails/action_handler.rb
276
278
  - lib/appmap/rails/sql_handler.rb
277
279
  - lib/appmap/railtie.rb
278
280
  - lib/appmap/rspec.rb
279
281
  - lib/appmap/trace.rb
282
+ - lib/appmap/util.rb
280
283
  - lib/appmap/version.rb
281
284
  - lore/pages/2019-05-21-install-and-record/index.pug
282
285
  - lore/pages/2019-05-21-install-and-record/install_example_appmap.png
@@ -436,6 +439,10 @@ files:
436
439
  - spec/fixtures/rails_users_app/db/migrate/20190728211408_create_users.rb
437
440
  - spec/fixtures/rails_users_app/db/schema.rb
438
441
  - spec/fixtures/rails_users_app/docker-compose.yml
442
+ - spec/fixtures/rails_users_app/features/api_users.feature
443
+ - spec/fixtures/rails_users_app/features/support/env.rb
444
+ - spec/fixtures/rails_users_app/features/support/hooks.rb
445
+ - spec/fixtures/rails_users_app/features/support/steps.rb
439
446
  - spec/fixtures/rails_users_app/lib/tasks/.keep
440
447
  - spec/fixtures/rails_users_app/log/.keep
441
448
  - spec/fixtures/rails_users_app/public/robots.txt
@@ -452,9 +459,26 @@ files:
452
459
  - spec/remote_recording_spec.rb
453
460
  - spec/rspec_feature_metadata_spec.rb
454
461
  - spec/spec_helper.rb
462
+ - spec/util_spec.rb
455
463
  - test/cli_test.rb
464
+ - test/cucumber_test.rb
456
465
  - test/fixtures/cli_record_test/appmap.yml
457
466
  - test/fixtures/cli_record_test/lib/cli_record_test/main.rb
467
+ - test/fixtures/cucumber4_recorder/Gemfile
468
+ - test/fixtures/cucumber4_recorder/appmap.yml
469
+ - test/fixtures/cucumber4_recorder/features/say_hello.feature
470
+ - test/fixtures/cucumber4_recorder/features/support/env.rb
471
+ - test/fixtures/cucumber4_recorder/features/support/hooks.rb
472
+ - test/fixtures/cucumber4_recorder/features/support/steps.rb
473
+ - test/fixtures/cucumber4_recorder/lib/hello.rb
474
+ - test/fixtures/cucumber_recorder/.bundle/config
475
+ - test/fixtures/cucumber_recorder/Gemfile
476
+ - test/fixtures/cucumber_recorder/appmap.yml
477
+ - test/fixtures/cucumber_recorder/features/say_hello.feature
478
+ - test/fixtures/cucumber_recorder/features/support/env.rb
479
+ - test/fixtures/cucumber_recorder/features/support/hooks.rb
480
+ - test/fixtures/cucumber_recorder/features/support/steps.rb
481
+ - test/fixtures/cucumber_recorder/lib/hello.rb
458
482
  - test/fixtures/rspec_recorder/Gemfile
459
483
  - test/fixtures/rspec_recorder/appmap.yml
460
484
  - test/fixtures/rspec_recorder/lib/hello.rb