infinity_test 1.0.3 → 2.0.0.rc1

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 (148) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +31 -0
  3. data/.gitignore +3 -0
  4. data/.rspec +2 -2
  5. data/AI_INTEGRATION_IDEAS.md +203 -0
  6. data/Gemfile +3 -15
  7. data/History.markdown +82 -0
  8. data/{.infinity_test → INFINITY_TEST} +18 -15
  9. data/LICENSE.txt +2 -2
  10. data/README.md +627 -0
  11. data/Rakefile +1 -65
  12. data/TODO.markdown +24 -19
  13. data/bin/infinity_test +1 -4
  14. data/images/fuuu/pending.png +0 -0
  15. data/images/fuuu/success.png +0 -0
  16. data/infinity_test.gemspec +41 -189
  17. data/lib/infinity_test/core/auto_discover.rb +67 -0
  18. data/lib/infinity_test/core/base.rb +369 -0
  19. data/lib/infinity_test/core/callback.rb +59 -0
  20. data/lib/infinity_test/core/changed_file.rb +13 -0
  21. data/lib/infinity_test/core/command_builder.rb +48 -0
  22. data/lib/infinity_test/core/command_runner.rb +62 -0
  23. data/lib/infinity_test/core/configuration_merge.rb +37 -0
  24. data/lib/infinity_test/core/continuous_test_server.rb +106 -0
  25. data/lib/infinity_test/core/load_configuration.rb +48 -0
  26. data/lib/infinity_test/core/notifier.rb +59 -0
  27. data/lib/infinity_test/core/options.rb +134 -0
  28. data/lib/infinity_test/core/runner.rb +18 -0
  29. data/lib/infinity_test/core/version.rb +5 -0
  30. data/lib/infinity_test/framework/base.rb +57 -0
  31. data/lib/infinity_test/framework/padrino.rb +33 -0
  32. data/lib/infinity_test/framework/rails.rb +35 -0
  33. data/lib/infinity_test/framework/rubygems.rb +29 -0
  34. data/lib/infinity_test/framework/shared_example.rb +47 -0
  35. data/lib/infinity_test/observer/base.rb +40 -0
  36. data/lib/infinity_test/observer/filewatcher.rb +72 -0
  37. data/lib/infinity_test/observer/listen.rb +74 -0
  38. data/lib/infinity_test/observer/shared_example.rb +35 -0
  39. data/lib/infinity_test/old_dsl/configuration.rb +26 -0
  40. data/lib/infinity_test/strategy/base.rb +34 -0
  41. data/lib/infinity_test/strategy/rbenv.rb +32 -0
  42. data/lib/infinity_test/strategy/ruby_default.rb +20 -0
  43. data/lib/infinity_test/strategy/rvm.rb +50 -0
  44. data/lib/infinity_test/strategy/shared_example.rb +32 -0
  45. data/lib/infinity_test/test_framework/base.rb +64 -0
  46. data/lib/infinity_test/test_framework/rspec.rb +48 -0
  47. data/lib/infinity_test/test_framework/shared_example.rb +56 -0
  48. data/lib/infinity_test/test_framework/test_unit.rb +57 -0
  49. data/lib/infinity_test.rb +53 -35
  50. data/spec/infinity_test/core/auto_discover_spec.rb +149 -0
  51. data/spec/infinity_test/core/base_spec.rb +240 -0
  52. data/spec/infinity_test/core/callback_spec.rb +89 -0
  53. data/spec/infinity_test/core/changed_file_spec.rb +26 -0
  54. data/spec/infinity_test/core/command_builder_spec.rb +38 -0
  55. data/spec/infinity_test/core/configuration_merge_spec.rb +124 -0
  56. data/spec/infinity_test/core/continuous_test_server_spec.rb +116 -0
  57. data/spec/infinity_test/core/load_configuration_spec.rb +43 -0
  58. data/spec/infinity_test/core/notifier_spec.rb +151 -0
  59. data/spec/infinity_test/core/options_spec.rb +168 -0
  60. data/spec/infinity_test/core/runner_spec.rb +17 -0
  61. data/spec/infinity_test/framework/base_spec.rb +55 -0
  62. data/spec/infinity_test/framework/padrino_spec.rb +36 -0
  63. data/spec/infinity_test/framework/rails_spec.rb +36 -0
  64. data/spec/infinity_test/framework/rubygems_spec.rb +34 -0
  65. data/spec/infinity_test/observer/base_spec.rb +78 -0
  66. data/spec/infinity_test/observer/filewatcher_spec.rb +51 -0
  67. data/spec/infinity_test/observer/listen_spec.rb +50 -0
  68. data/spec/infinity_test/{builder_spec.rb → strategy/base_spec.rb} +1 -2
  69. data/spec/infinity_test/strategy/rbenv_spec.rb +53 -0
  70. data/spec/infinity_test/strategy/ruby_default_spec.rb +32 -0
  71. data/spec/infinity_test/strategy/rvm_spec.rb +69 -0
  72. data/spec/infinity_test/test_framework/rspec_spec.rb +119 -0
  73. data/spec/infinity_test/test_framework/test_unit_spec.rb +193 -0
  74. data/spec/spec_helper.rb +34 -119
  75. metadata +272 -176
  76. data/.rvmrc +0 -1
  77. data/Gemfile.lock +0 -62
  78. data/Readme.markdown +0 -147
  79. data/Tasks +0 -4
  80. data/VERSION.yml +0 -5
  81. data/buzz_images/buzz_lightyear.jpg +0 -0
  82. data/buzz_images/buzz_lightyear_continencia.gif +0 -0
  83. data/buzz_images/to_infinity_and_beyond.png +0 -0
  84. data/features/heuristics.feature +0 -23
  85. data/features/support/env.rb +0 -2
  86. data/images/fuuu/sucess.png +0 -0
  87. data/lib/infinity_test/application.rb +0 -362
  88. data/lib/infinity_test/application_library/rails.rb +0 -94
  89. data/lib/infinity_test/application_library/rubygems.rb +0 -43
  90. data/lib/infinity_test/binary_path.rb +0 -43
  91. data/lib/infinity_test/builder.rb +0 -66
  92. data/lib/infinity_test/command.rb +0 -58
  93. data/lib/infinity_test/configuration.rb +0 -277
  94. data/lib/infinity_test/continuous_testing.rb +0 -40
  95. data/lib/infinity_test/dependencies.rb +0 -80
  96. data/lib/infinity_test/environment.rb +0 -15
  97. data/lib/infinity_test/heuristics.rb +0 -36
  98. data/lib/infinity_test/heuristics_helper.rb +0 -9
  99. data/lib/infinity_test/options.rb +0 -96
  100. data/lib/infinity_test/runner.rb +0 -38
  101. data/lib/infinity_test/test_framework.rb +0 -110
  102. data/lib/infinity_test/test_library/bacon.rb +0 -55
  103. data/lib/infinity_test/test_library/cucumber.rb +0 -22
  104. data/lib/infinity_test/test_library/rspec.rb +0 -60
  105. data/lib/infinity_test/test_library/test_unit.rb +0 -52
  106. data/lib/infinity_test/test_unit_loader.rb +0 -5
  107. data/spec/factories/buzz/lib/buzz.rb +0 -0
  108. data/spec/factories/buzz/spec/buzz_spec.rb +0 -0
  109. data/spec/factories/company/Gemfile +0 -0
  110. data/spec/factories/company/lib/company.rb +0 -0
  111. data/spec/factories/company/test/company_test.rb +0 -0
  112. data/spec/factories/images/failure.png +0 -0
  113. data/spec/factories/images/pending.png +0 -0
  114. data/spec/factories/images/sucess.png +0 -0
  115. data/spec/factories/infinity_test +0 -5
  116. data/spec/factories/infinity_test_example +0 -7
  117. data/spec/factories/slinky/spec/slinky/slinky_spec.rb +0 -0
  118. data/spec/factories/travel/lib/travel.rb +0 -0
  119. data/spec/factories/travel/test/partner_test.rb +0 -0
  120. data/spec/factories/travel/test/travel_test.rb +0 -0
  121. data/spec/factories/wood/lib/wood.rb +0 -0
  122. data/spec/factories/wood/spec/wood_spec.rb +0 -0
  123. data/spec/infinity_test/application_library/rails_spec.rb +0 -140
  124. data/spec/infinity_test/application_library/rubygems_spec.rb +0 -52
  125. data/spec/infinity_test/application_spec.rb +0 -434
  126. data/spec/infinity_test/binary_path_spec.rb +0 -72
  127. data/spec/infinity_test/command_spec.rb +0 -53
  128. data/spec/infinity_test/configuration_spec.rb +0 -382
  129. data/spec/infinity_test/continuous_testing_spec.rb +0 -25
  130. data/spec/infinity_test/environment_spec.rb +0 -23
  131. data/spec/infinity_test/heuristics_helper_spec.rb +0 -15
  132. data/spec/infinity_test/heuristics_spec.rb +0 -127
  133. data/spec/infinity_test/options_spec.rb +0 -111
  134. data/spec/infinity_test/runner_spec.rb +0 -42
  135. data/spec/infinity_test/test_framework_spec.rb +0 -127
  136. data/spec/infinity_test/test_library/bacon_spec.rb +0 -150
  137. data/spec/infinity_test/test_library/cucumber_spec.rb +0 -8
  138. data/spec/infinity_test/test_library/rspec_spec.rb +0 -189
  139. data/spec/infinity_test/test_library/test_unit_spec.rb +0 -184
  140. data/spec/infinity_test_spec.rb +0 -40
  141. /data/images/faces/{sucess.png → success.png} +0 -0
  142. /data/images/hands/{sucess.png → success.png} +0 -0
  143. /data/images/mario_bros/{sucess.jpg → success.jpg} +0 -0
  144. /data/images/rails/{sucess.png → success.png} +0 -0
  145. /data/images/rubies/{sucess.png → success.png} +0 -0
  146. /data/images/simpson/{sucess.jpg → success.jpg} +0 -0
  147. /data/images/street_fighter/{sucess.jpg → success.jpg} +0 -0
  148. /data/images/toy_story/{sucess.png → success.png} +0 -0
@@ -0,0 +1,48 @@
1
+ module InfinityTest
2
+ module Core
3
+ class LoadConfiguration
4
+ attr_accessor :global_file, :project_file
5
+
6
+ def initialize
7
+ @global_file = File.expand_path('~/INFINITY_TEST')
8
+ @project_file = './INFINITY_TEST'
9
+ @old_configuration = InfinityTest::OldDSL::Configuration
10
+ end
11
+
12
+ # Load the Configuration file
13
+ #
14
+ # Command line options can be persisted in an INFINITY_TEST file in a project.
15
+ # You can also store an INFINITY_TEST file in your home directory (~/INFINITY_TEST)
16
+ #
17
+ # Precedence is:
18
+ # command line
19
+ # ./INFINITY_TEST
20
+ # ~/INFINITY_TEST
21
+ #
22
+ # Example:
23
+ #
24
+ # ~/INFINITY_TEST -> infinity_test { notifications :osascript }
25
+ #
26
+ # ./INFINITY_TEST -> infinity_test { notifications :terminal_notifier } # High Priority
27
+ #
28
+ # After the load the Notifications Framework will be Terminal Notifier
29
+ #
30
+ def load!
31
+ load_global_file!
32
+ load_project_file!
33
+ end
34
+
35
+ def load_global_file!
36
+ load_file(@global_file)
37
+ end
38
+
39
+ def load_project_file!
40
+ load_file(@project_file)
41
+ end
42
+
43
+ def load_file(file)
44
+ load(file) if File.exist?(file)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,59 @@
1
+ module InfinityTest
2
+ module Core
3
+ class Notifier
4
+ include ::Notifiers
5
+
6
+ attr_reader :test_framework, :library
7
+
8
+ IMAGES = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'images'))
9
+
10
+ delegate :test_message, to: :test_framework
11
+
12
+ def initialize(options)
13
+ @test_framework = options.fetch(:test_framework)
14
+ @library = options.fetch(:library)
15
+ end
16
+
17
+ def notify
18
+ send(library).title(RUBY_VERSION).message(test_message).image(image).notify
19
+ end
20
+
21
+ def image
22
+ return success_image if test_framework.success?
23
+
24
+ if test_framework.failure?
25
+ failure_image
26
+ else
27
+ pending_image
28
+ end
29
+ end
30
+
31
+ def success_image
32
+ Core::Base.success_image || find_image(:success)
33
+ end
34
+
35
+ def failure_image
36
+ Core::Base.failure_image || find_image(:failure)
37
+ end
38
+
39
+ def pending_image
40
+ Core::Base.pending_image || find_image(:pending)
41
+ end
42
+
43
+ def find_image(image_type)
44
+ Dir.glob(File.join(images_dir, "#{image_type.to_s}*")).first
45
+ end
46
+
47
+ def images_dir
48
+ mode = Core::Base.mode
49
+
50
+ case mode
51
+ when Symbol
52
+ File.join(IMAGES, mode.to_s)
53
+ when String
54
+ File.expand_path(File.join(mode))
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,134 @@
1
+ module InfinityTest
2
+ module Core
3
+ class Options
4
+ attr_accessor :arguments, :options_parser, :strategy, :bundler, :verbose
5
+ attr_accessor :rubies, :specific_options, :test_framework, :framework, :infinity_and_beyond
6
+ attr_accessor :notifications, :mode, :just_watch, :focus
7
+
8
+ def initialize(*arguments)
9
+ @arguments = arguments.flatten.clone
10
+ @options_parser = new_options_parser
11
+ end
12
+
13
+ def new_options_parser
14
+ OptionParser.new do |option|
15
+ %w(
16
+ ruby_strategy
17
+ ruby_versions
18
+ options_to_added_in_the_command
19
+ test_framework_to_be_run
20
+ app_framework
21
+ notifications_library
22
+ image_mode
23
+ infinity_and_beyond_option
24
+ just_watch_option
25
+ focus_option
26
+ verbose_mode
27
+ skip_bundler
28
+ ).each do |option_to_parse|
29
+ send(option_to_parse, option)
30
+ end
31
+ banner(option)
32
+ help(option)
33
+ end
34
+ end
35
+
36
+ def parse!
37
+ @options_parser.parse!(@arguments)
38
+
39
+ self
40
+ end
41
+
42
+ def ruby_strategy(option)
43
+ option.on('--ruby strategy', 'Ruby Manager. Ex.: auto_discover, rvm, rbenv, ruby_default') do |strategy|
44
+ @strategy = strategy.to_sym
45
+ end
46
+ end
47
+
48
+ def ruby_versions(option)
49
+ option.on('--rubies=rubies', 'Specify Ruby version(s) to test against') do |versions|
50
+ @rubies = versions.split(',')
51
+ end
52
+ end
53
+
54
+ def options_to_added_in_the_command(option)
55
+ option.on('--options=options', 'Pass the options to be added. Ex. -Ilib-Itest-Iapp') do |options|
56
+ @specific_options = options.split('-').join(' -').strip
57
+ end
58
+ end
59
+
60
+ def test_framework_to_be_run(option)
61
+ option.on('--test library', 'Test Framework to be run. Ex.: auto_discover, rspec, test_unit.') do |library|
62
+ @test_framework = library.to_sym
63
+ end
64
+ end
65
+
66
+ def app_framework(option)
67
+ option.on('--framework library', 'Application Framework to be run and added the patterns to search changed files. Ex.: auto_discover, rails, rubygems, padrino.') do |library|
68
+ @framework = library.to_sym
69
+ end
70
+ end
71
+
72
+ def notifications_library(option)
73
+ option.on('--notifications library', 'Notification library to use. Ex.: auto_discover, osascript, terminal_notifier, notify_send, dunstify.') do |library|
74
+ @notifications = library.to_sym
75
+ end
76
+ end
77
+
78
+ def image_mode(option)
79
+ option.on('--mode theme', 'Image theme for notifications. Ex.: simpson, faces, fuuu, hands, mario_bros, rails, rubies, street_fighter, toy_story.') do |theme|
80
+ @mode = theme.to_sym
81
+ end
82
+ end
83
+
84
+ def infinity_and_beyond_option(option)
85
+ option.on('-n', '--no-infinity-and-beyond', 'Run tests and exit. Useful in a Continuous Integration environment.') do
86
+ @infinity_and_beyond = false
87
+ end
88
+ end
89
+
90
+ def just_watch_option(option)
91
+ option.on('-j', '--just-watch', 'Skip initial test run and only watch for file changes. Useful for large applications.') do
92
+ @just_watch = true
93
+ end
94
+ end
95
+
96
+ def focus_option(option)
97
+ option.on('-f', '--focus [FILE]', 'Focus on specific tests. Use "failures" for failed tests, or provide a file path.') do |file|
98
+ @focus = file == 'failures' ? :failures : file
99
+ end
100
+ end
101
+
102
+ def verbose_mode(option)
103
+ option.on('--no-verbose', "Don't print commands before executing them") do
104
+ @verbose = false
105
+ end
106
+ end
107
+
108
+ def skip_bundler(option)
109
+ option.on('--no-bundler', "Bypass Infinity Test's Bundler support") do
110
+ @bundler = false
111
+ end
112
+ end
113
+
114
+ def banner(option)
115
+ option.banner = [ "Usage: infinity_test [options]", "Run tests"].join("\n")
116
+ end
117
+
118
+ def help(option)
119
+ option.on_tail("--help", "You're looking at it.") do
120
+ print option.help
121
+ exit
122
+ end
123
+ end
124
+
125
+ def verbose?
126
+ @verbose
127
+ end
128
+
129
+ def bundler?
130
+ @bundler
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,18 @@
1
+ module InfinityTest
2
+ module Core
3
+ class Runner
4
+ attr_accessor :options
5
+
6
+ def initialize(*arguments)
7
+ @options = Options.new(arguments).parse!
8
+ end
9
+
10
+ def start
11
+ Core::LoadConfiguration.new.load!
12
+ Core::Base.merge!(options)
13
+ Core::AutoDiscover.new(Core::Base).discover_libraries
14
+ Core::Base.start_continuous_test_server
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module InfinityTest
2
+ module Core
3
+ VERSION = '2.0.0.rc1'
4
+ end
5
+ end
@@ -0,0 +1,57 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Base
4
+ attr_reader :continuous_test_server, :hike
5
+ delegate :observer, :test_framework, :extension, to: :continuous_test_server
6
+ delegate :watch, :watch_dir, to: :observer
7
+
8
+ def initialize(continuous_test_server)
9
+ @continuous_test_server = continuous_test_server
10
+ @hike = Hike::Trail.new(Dir.pwd)
11
+ end
12
+
13
+ def heuristics!
14
+ hike.append_extension(extension)
15
+ hike.append_path(test_framework.test_dir)
16
+ heuristics
17
+ end
18
+
19
+ # This method is called for the InfinityTest before starting the observer
20
+ #
21
+ def heuristics
22
+ raise NotImplementedError, "not implemented in #{self}"
23
+ end
24
+
25
+ # Put all the requires to autodiscover use your framework instead of others.
26
+ #
27
+ def self.run?
28
+ raise NotImplementedError, "not implemented in #{self}"
29
+ end
30
+
31
+ # Run all the strategy again.
32
+ #
33
+ def run_all
34
+ continuous_test_server.run_strategy
35
+ end
36
+
37
+ # Run the same changed file.
38
+ # E.g: the user saves the test file, runs the test file.
39
+ #
40
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
41
+ #
42
+ def run_file(changed_file)
43
+ continuous_test_server.rerun_strategy(changed_file.name)
44
+ end
45
+
46
+ # Run test based on the changed file.
47
+ #
48
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
49
+ #
50
+ def run_test(changed_file)
51
+ file_name = "#{changed_file.path}_#{test_framework.test_dir}.#{extension}"
52
+ file = hike.find(file_name)
53
+ continuous_test_server.rerun_strategy(file) if file.present?
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Padrino < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Add Heuristics to the observer run on pattern changes!
7
+ #
8
+ # ==== Heuristics
9
+ # * Watch app folder (models, controllers, helpers, mailers) and run corresponding tests/specs
10
+ # * Watch lib dir and run corresponding tests
11
+ # * Watch test/spec dir and run the changed file
12
+ # * Watch test/spec helper and run all
13
+ #
14
+ def heuristics
15
+ watch_dir('app/models') { |file| run_test(file) }
16
+ watch_dir('app/controllers') { |file| run_test(file) }
17
+ watch_dir('app/helpers') { |file| run_test(file) }
18
+ watch_dir('app/mailers') { |file| run_test(file) }
19
+ watch_dir(:lib) { |file| run_test(file) }
20
+ watch_dir(test_dir) { |file| run_file(file) }
21
+ watch(test_helper_file) { run_all }
22
+ end
23
+
24
+ # ==== Returns
25
+ # TrueClass: Find the config/apps.rb in the user current dir
26
+ # FalseClass: Don't Find the config/apps.rb in the user current dir
27
+ #
28
+ def self.run?
29
+ File.exist?(File.expand_path('./config/apps.rb'))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Rails < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Add Heuristics to the observer run on pattern changes!
7
+ #
8
+ # ==== Heuristics
9
+ # * Watch app/models and run corresponding tests/specs
10
+ # * Watch app/controllers and run corresponding tests/specs
11
+ # * Watch app/helpers and run corresponding tests/specs
12
+ # * Watch app/mailers and run corresponding tests/specs
13
+ # * Watch app/jobs and run corresponding tests/specs
14
+ # * Watch lib dir and run corresponding tests
15
+ # * Watch test/spec dir and run the changed file
16
+ # * Watch test/spec helper and run all
17
+ # * Watch config/routes.rb and run routing specs
18
+ #
19
+ def heuristics
20
+ watch_dir('app/models') { |file| run_test(file) }
21
+ watch_dir('app/controllers') { |file| run_test(file) }
22
+ watch_dir('app/helpers') { |file| run_test(file) }
23
+ watch_dir('app/mailers') { |file| run_test(file) }
24
+ watch_dir('app/jobs') { |file| run_test(file) }
25
+ watch_dir(:lib) { |file| run_test(file) }
26
+ watch_dir(test_dir) { |file| run_file(file) }
27
+ watch(test_helper_file) { run_all }
28
+ end
29
+
30
+ def self.run?
31
+ File.exist?(File.expand_path('./config/environment.rb'))
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Rubygems < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Add Heuristics to the observer run on pattern changes!
7
+ #
8
+ # ==== Heuristics
9
+ # * Add Gemfile and Run bundle install and run all specs.
10
+ # * Observe lib dir and run test.
11
+ # * Observe the test dir and run the same changed file.
12
+ # * Observe the test helper file and run.
13
+ #
14
+ def heuristics
15
+ watch_dir(:lib) { |file| run_test(file) }
16
+ watch_dir(test_dir) { |file| run_file(file) }
17
+ watch(test_helper_file) { run_all }
18
+ end
19
+
20
+ # ==== Returns
21
+ # TrueClass: Find a gemspec in the user current dir
22
+ # FalseClass: Don't Find a gemspec in the user current dir
23
+ #
24
+ def self.run?
25
+ Dir["*.gemspec"].present?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ module InfinityTest
2
+ module Framework
3
+ module SharedExample
4
+ # Shared Examples to use in the RSpec specs when you want create your own observer.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # RSpec.configure do |config|
9
+ # config.include InfinityTest::Observer::SharedExample
10
+ # end
11
+ #
12
+ # describe BarObserver do
13
+ # it_should_behave_like 'an infinity test observer'
14
+ # end
15
+ #
16
+ shared_examples_for 'an infinity test framework' do
17
+ it 'responds to #heuristics' do
18
+ expect(subject).to respond_to(:heuristics)
19
+ end
20
+
21
+ it 'responds to #heuristics!' do
22
+ expect(subject).to respond_to(:heuristics!)
23
+ end
24
+
25
+ it 'responds to .run?' do
26
+ expect(subject.class).to respond_to(:run?)
27
+ end
28
+
29
+ it 'responds to #base' do
30
+ expect(subject).to respond_to(:base)
31
+ end
32
+
33
+ it 'responds to #test_framework' do
34
+ expect(subject).to respond_to(:test_framework)
35
+ end
36
+
37
+ it 'responds to #strategy' do
38
+ expect(subject).to respond_to(:strategy)
39
+ end
40
+
41
+ it 'responds to #observer' do
42
+ expect(subject).to respond_to(:observer)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ module InfinityTest
2
+ module Observer
3
+ class Base
4
+ attr_accessor :continuous_test_server
5
+
6
+ def initialize(continuous_test_server)
7
+ @continuous_test_server = continuous_test_server
8
+ end
9
+
10
+ def watch(pattern_or_file, &block)
11
+ raise NotImplementedError, "not implemented in #{self}"
12
+ end
13
+
14
+ def watch_dir(dir_name, extension, &block)
15
+ raise NotImplementedError, "not implemented in #{self}"
16
+ end
17
+
18
+ def start!
19
+ signal
20
+ start
21
+ end
22
+
23
+ def start
24
+ raise NotImplementedError, "not implemented in #{self}"
25
+ end
26
+
27
+ def signal
28
+ Signal.trap('INT') do
29
+ if @interrupt_at && (Time.now - @interrupt_at) < 2
30
+ puts " To Infinity and Beyond!"
31
+ exit
32
+ else
33
+ puts " Are you sure? :S ... Interrupt a second time to quit!"
34
+ @interrupt_at = Time.now
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,72 @@
1
+ require 'filewatcher'
2
+
3
+ module InfinityTest
4
+ module Observer
5
+ class Filewatcher < Base
6
+ attr_reader :observer, :watch_paths, :patterns
7
+
8
+ def initialize(continuous_test_server)
9
+ super
10
+ @watch_paths = []
11
+ @patterns = {}
12
+ end
13
+
14
+ # Watch a file or pattern for changes.
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # watch('lib/(.*)\.rb') { |file| puts [file.name, file.path, file.match_data] }
19
+ # watch('test/test_helper.rb') { run_all() }
20
+ #
21
+ def watch(pattern_or_file, &block)
22
+ pattern = Regexp.new(pattern_or_file.to_s)
23
+ @patterns[pattern] = block
24
+ end
25
+
26
+ # Watch a directory for changes.
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # watch_dir(:lib) { |file| run_test(file) }
31
+ # watch_dir(:test) { |file| run_file(file) }
32
+ #
33
+ # watch_dir(:test, :py) { |file| puts [file.name, file.path, file.match_data] }
34
+ # watch_dir(:test, :js) { |file| puts [file.name, file.path, file.match_data] }
35
+ #
36
+ def watch_dir(dir_name, extension = :rb, &block)
37
+ watch("^#{dir_name}/*/(.*).#{extension}", &block)
38
+ path = "#{dir_name}/**/*.#{extension}"
39
+ @watch_paths << path unless @watch_paths.include?(path)
40
+ end
41
+
42
+ # Start the continuous test server.
43
+ #
44
+ def start
45
+ paths = @watch_paths.empty? ? ['**/*.rb'] : @watch_paths
46
+
47
+ @observer = ::Filewatcher.new(paths)
48
+
49
+ @observer.watch do |changes|
50
+ changes.each do |file_path, _event|
51
+ relative_path = file_path.sub("#{Dir.pwd}/", '')
52
+ handle_file_change(relative_path)
53
+ end
54
+ end
55
+ rescue Interrupt
56
+ @observer.stop if @observer
57
+ end
58
+
59
+ private
60
+
61
+ def handle_file_change(file_path)
62
+ @patterns.each do |pattern, block|
63
+ if match_data = pattern.match(file_path)
64
+ changed_file = InfinityTest::Core::ChangedFile.new(match_data)
65
+ block.call(changed_file)
66
+ break
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,74 @@
1
+ require 'listen'
2
+
3
+ module InfinityTest
4
+ module Observer
5
+ class Listen < Base
6
+ attr_reader :observer, :directories, :patterns
7
+
8
+ def initialize(continuous_test_server)
9
+ super
10
+ @directories = []
11
+ @patterns = {}
12
+ end
13
+
14
+ # Watch a file or pattern for changes.
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # watch('lib/(.*)\.rb') { |file| puts [file.name, file.path, file.match_data] }
19
+ # watch('test/test_helper.rb') { run_all() }
20
+ #
21
+ def watch(pattern_or_file, &block)
22
+ pattern = Regexp.new(pattern_or_file.to_s)
23
+ @patterns[pattern] = block
24
+ end
25
+
26
+ # Watch a directory for changes.
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # watch_dir(:lib) { |file| run_test(file) }
31
+ # watch_dir(:test) { |file| run_file(file) }
32
+ #
33
+ # watch_dir(:test, :py) { |file| puts [file.name, file.path, file.match_data] }
34
+ # watch_dir(:test, :js) { |file| puts [file.name, file.path, file.match_data] }
35
+ #
36
+ def watch_dir(dir_name, extension = :rb, &block)
37
+ watch("^#{dir_name}/*/(.*).#{extension}", &block)
38
+ @directories << dir_name.to_s unless @directories.include?(dir_name.to_s)
39
+ end
40
+
41
+ # Start the continuous test server.
42
+ #
43
+ def start
44
+ dirs = @directories.empty? ? ['.'] : @directories
45
+ dirs = dirs.select { |d| File.directory?(d) }
46
+ dirs = ['.'] if dirs.empty?
47
+
48
+ @observer = ::Listen.to(*dirs) do |modified, added, _removed|
49
+ (modified + added).each do |file|
50
+ relative_path = file.sub("#{Dir.pwd}/", '')
51
+ handle_file_change(relative_path)
52
+ end
53
+ end
54
+
55
+ @observer.start
56
+ sleep
57
+ rescue Interrupt
58
+ @observer.stop if @observer
59
+ end
60
+
61
+ private
62
+
63
+ def handle_file_change(file_path)
64
+ @patterns.each do |pattern, block|
65
+ if match_data = pattern.match(file_path)
66
+ changed_file = InfinityTest::Core::ChangedFile.new(match_data)
67
+ block.call(changed_file)
68
+ break
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ module InfinityTest
2
+ module Observer
3
+ module SharedExample
4
+ # Shared Examples to use in the RSpec specs when you want create your own observer.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # RSpec.configure do |config|
9
+ # config.include InfinityTest::Observer::SharedExample
10
+ # end
11
+ #
12
+ # describe BarObserver do
13
+ # it_should_behave_like 'an infinity test observer'
14
+ # end
15
+ #
16
+ shared_examples_for 'an infinity test observer' do
17
+ it 'responds to #observer' do
18
+ expect(subject).to respond_to(:observer)
19
+ end
20
+
21
+ it 'responds to #watch_dir' do
22
+ expect(subject).to respond_to(:watch_dir)
23
+ end
24
+
25
+ it 'responds to #watch' do
26
+ expect(subject).to respond_to(:watch)
27
+ end
28
+
29
+ it 'responds to #start' do
30
+ expect(subject).to respond_to(:start)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end