infinity_test 2.0.0.rc1 → 2.0.0.rc2

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +84 -0
  3. data/README.md +249 -9
  4. data/TODO.markdown +36 -27
  5. data/lib/infinity_test/core/auto_discover.rb +3 -3
  6. data/lib/infinity_test/core/command_runner.rb +16 -40
  7. data/lib/infinity_test/core/continuous_test_server.rb +18 -0
  8. data/lib/infinity_test/core/version.rb +1 -1
  9. data/lib/infinity_test/framework/base.rb +36 -0
  10. data/lib/infinity_test/framework/django.rb +109 -0
  11. data/lib/infinity_test/framework/elixir_mix.rb +47 -0
  12. data/lib/infinity_test/framework/fast_api.rb +104 -0
  13. data/lib/infinity_test/framework/padrino.rb +5 -8
  14. data/lib/infinity_test/framework/phoenix.rb +72 -0
  15. data/lib/infinity_test/framework/python_package.rb +97 -0
  16. data/lib/infinity_test/framework/rails.rb +5 -14
  17. data/lib/infinity_test/framework/rocket.rb +70 -0
  18. data/lib/infinity_test/framework/rust_cargo.rb +69 -0
  19. data/lib/infinity_test/strategy/base.rb +17 -1
  20. data/lib/infinity_test/strategy/elixir_default.rb +20 -0
  21. data/lib/infinity_test/strategy/python_default.rb +22 -0
  22. data/lib/infinity_test/strategy/rbenv.rb +3 -1
  23. data/lib/infinity_test/strategy/ruby_default.rb +2 -1
  24. data/lib/infinity_test/strategy/rust_default.rb +21 -0
  25. data/lib/infinity_test/strategy/rvm.rb +3 -1
  26. data/lib/infinity_test/test_framework/cargo_test.rb +49 -0
  27. data/lib/infinity_test/test_framework/ex_unit.rb +53 -0
  28. data/lib/infinity_test/test_framework/pytest.rb +65 -0
  29. data/lib/infinity_test.rb +13 -0
  30. data/spec/infinity_test/core/auto_discover_spec.rb +29 -3
  31. data/spec/infinity_test/framework/django_spec.rb +95 -0
  32. data/spec/infinity_test/framework/elixir_mix_spec.rb +44 -0
  33. data/spec/infinity_test/framework/fast_api_spec.rb +96 -0
  34. data/spec/infinity_test/framework/padrino_spec.rb +28 -6
  35. data/spec/infinity_test/framework/phoenix_spec.rb +85 -0
  36. data/spec/infinity_test/framework/python_package_spec.rb +95 -0
  37. data/spec/infinity_test/framework/rails_spec.rb +28 -6
  38. data/spec/infinity_test/framework/rocket_spec.rb +69 -0
  39. data/spec/infinity_test/framework/rust_cargo_spec.rb +94 -0
  40. data/spec/infinity_test/strategy/elixir_default_spec.rb +46 -0
  41. data/spec/infinity_test/strategy/python_default_spec.rb +56 -0
  42. data/spec/infinity_test/strategy/rbenv_spec.rb +19 -2
  43. data/spec/infinity_test/strategy/ruby_default_spec.rb +19 -2
  44. data/spec/infinity_test/strategy/rust_default_spec.rb +56 -0
  45. data/spec/infinity_test/strategy/rvm_spec.rb +23 -6
  46. data/spec/infinity_test/test_framework/cargo_test_spec.rb +145 -0
  47. data/spec/infinity_test/test_framework/ex_unit_spec.rb +153 -0
  48. data/spec/infinity_test/test_framework/pytest_spec.rb +182 -0
  49. metadata +47 -5
@@ -0,0 +1,22 @@
1
+ module InfinityTest
2
+ module Strategy
3
+ class PythonDefault < Base
4
+ attr_reader :continuous_test_server
5
+ delegate :binary, :test_files, to: :continuous_test_server
6
+
7
+ def run!
8
+ command = "#{binary} #{test_files}"
9
+ command = "#{command} #{Core::Base.specific_options}" if Core::Base.specific_options.present?
10
+ command
11
+ end
12
+
13
+ # Run when the project has Python package files
14
+ #
15
+ def self.run?
16
+ File.exist?('pyproject.toml') ||
17
+ File.exist?('setup.py') ||
18
+ File.exist?('setup.cfg')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -14,7 +14,9 @@ module InfinityTest
14
14
  rubies = Core::Base.rubies
15
15
 
16
16
  commands = rubies.map do |ruby_version|
17
- "RBENV_VERSION=#{ruby_version} #{command_builder.ruby.option(:S).add(binary).add(test_files).to_s}"
17
+ test_command = "#{binary} #{test_files}"
18
+ test_command = with_bundler(test_command)
19
+ "RBENV_VERSION=#{ruby_version} #{test_command}"
18
20
  end
19
21
 
20
22
  commands.join(' && ')
@@ -5,7 +5,8 @@ module InfinityTest
5
5
  delegate :binary, :test_files, to: :continuous_test_server
6
6
 
7
7
  def run!
8
- command_builder.ruby.option(:S).add(binary).add(test_files).to_s
8
+ command = "#{binary} #{test_files}"
9
+ with_bundler(command)
9
10
  end
10
11
 
11
12
  # ==== Returns
@@ -0,0 +1,21 @@
1
+ module InfinityTest
2
+ module Strategy
3
+ class RustDefault < Base
4
+ attr_reader :continuous_test_server
5
+ delegate :binary, :test_files, to: :continuous_test_server
6
+
7
+ def run!
8
+ command = "#{binary} test"
9
+ command = "#{command} #{test_files}" if test_files.present?
10
+ command = "#{command} #{Core::Base.specific_options}" if Core::Base.specific_options.present?
11
+ command
12
+ end
13
+
14
+ # Run when the project has Cargo.toml (Rust project)
15
+ #
16
+ def self.run?
17
+ File.exist?('Cargo.toml')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -16,7 +16,9 @@ module InfinityTest
16
16
 
17
17
  commands = rubies.map do |ruby_version|
18
18
  ruby_with_gemset = gemset.present? ? "#{ruby_version}@#{gemset}" : ruby_version
19
- command_builder.rvm.add(ruby_with_gemset).do.ruby.option(:S).add(binary).add(test_files).to_s
19
+ test_command = "#{binary} #{test_files}"
20
+ test_command = with_bundler(test_command)
21
+ "rvm #{ruby_with_gemset} do #{test_command}"
20
22
  end
21
23
 
22
24
  commands.join(' && ')
@@ -0,0 +1,49 @@
1
+ module InfinityTest
2
+ module TestFramework
3
+ class CargoTest < Base
4
+ def binary
5
+ 'cargo'
6
+ end
7
+
8
+ def test_helper_file
9
+ 'Cargo.toml'
10
+ end
11
+
12
+ def test_dir
13
+ @test_dir ||= 'tests'
14
+ end
15
+
16
+ def test_dir=(dir)
17
+ @test_dir = dir
18
+ end
19
+
20
+ def test_files
21
+ @test_files || ''
22
+ end
23
+
24
+ # Cargo test output patterns:
25
+ # "test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out"
26
+ # "test result: FAILED. 3 passed; 2 failed; 1 ignored; 0 measured; 0 filtered out"
27
+ #
28
+ def patterns
29
+ { passed: /(\d+) passed/, failed: /(\d+) failed/, ignored: /(\d+) ignored/ }
30
+ end
31
+
32
+ def success?
33
+ @failed.zero? && @ignored.zero?
34
+ end
35
+
36
+ def failure?
37
+ @failed > 0
38
+ end
39
+
40
+ def pending?
41
+ @ignored > 0
42
+ end
43
+
44
+ def self.run?
45
+ File.exist?('Cargo.toml')
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ module InfinityTest
2
+ module TestFramework
3
+ class ExUnit < Base
4
+ def binary
5
+ 'mix'
6
+ end
7
+
8
+ def test_helper_file
9
+ File.join(test_dir, 'test_helper.exs')
10
+ end
11
+
12
+ def test_dir
13
+ @test_dir ||= 'test'
14
+ end
15
+
16
+ def test_dir=(dir)
17
+ @test_dir = dir
18
+ end
19
+
20
+ def test_files
21
+ @test_files || test_dir
22
+ end
23
+
24
+ # ExUnit output patterns:
25
+ # "3 tests, 0 failures"
26
+ # "3 tests, 1 failure"
27
+ # "3 tests, 0 failures, 1 skipped"
28
+ #
29
+ def patterns
30
+ { tests: /(\d+) tests?/, failures: /(\d+) failures?/, skipped: /(\d+) skipped/ }
31
+ end
32
+
33
+ def success?
34
+ @failures.zero? && @skipped.zero?
35
+ end
36
+
37
+ def failure?
38
+ @failures > 0
39
+ end
40
+
41
+ def pending?
42
+ @skipped > 0
43
+ end
44
+
45
+ def self.run?
46
+ File.exist?('test') && (
47
+ File.exist?('test/test_helper.exs') ||
48
+ Dir['test/**/*_test.exs'].any?
49
+ )
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,65 @@
1
+ module InfinityTest
2
+ module TestFramework
3
+ class Pytest < Base
4
+ def binary
5
+ 'pytest'
6
+ end
7
+
8
+ def test_helper_file
9
+ File.join(test_dir, 'conftest.py')
10
+ end
11
+
12
+ def test_dir
13
+ @test_dir ||= detect_test_dir
14
+ end
15
+
16
+ def test_dir=(dir)
17
+ @test_dir = dir
18
+ end
19
+
20
+ def test_files
21
+ @test_files || test_dir
22
+ end
23
+
24
+ # Pytest output patterns:
25
+ # "5 passed in 0.12s"
26
+ # "1 failed, 4 passed in 0.15s"
27
+ # "1 failed, 2 passed, 1 skipped in 0.20s"
28
+ #
29
+ def patterns
30
+ { passed: /(\d+) passed/, failed: /(\d+) failed/, skipped: /(\d+) skipped/ }
31
+ end
32
+
33
+ def success?
34
+ @failed.zero? && @skipped.zero?
35
+ end
36
+
37
+ def failure?
38
+ @failed > 0
39
+ end
40
+
41
+ def pending?
42
+ @skipped > 0
43
+ end
44
+
45
+ def self.run?
46
+ (File.exist?('tests') || File.exist?('test')) && (
47
+ File.exist?('tests/conftest.py') ||
48
+ File.exist?('test/conftest.py') ||
49
+ Dir['tests/**/test_*.py'].any? ||
50
+ Dir['test/**/test_*.py'].any? ||
51
+ Dir['tests/**/*_test.py'].any? ||
52
+ Dir['test/**/*_test.py'].any?
53
+ )
54
+ end
55
+
56
+ private
57
+
58
+ def detect_test_dir
59
+ return 'tests' if File.exist?('tests')
60
+ return 'test' if File.exist?('test')
61
+ 'tests'
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/infinity_test.rb CHANGED
@@ -62,8 +62,21 @@ end
62
62
  require 'infinity_test/strategy/rbenv'
63
63
  require 'infinity_test/strategy/rvm'
64
64
  require 'infinity_test/strategy/ruby_default'
65
+ require 'infinity_test/strategy/elixir_default'
66
+ require 'infinity_test/strategy/python_default'
67
+ require 'infinity_test/strategy/rust_default'
65
68
  require 'infinity_test/framework/padrino'
66
69
  require 'infinity_test/framework/rails'
67
70
  require 'infinity_test/framework/rubygems'
71
+ require 'infinity_test/framework/elixir_mix'
72
+ require 'infinity_test/framework/phoenix'
73
+ require 'infinity_test/framework/python_package'
74
+ require 'infinity_test/framework/fast_api'
75
+ require 'infinity_test/framework/django'
76
+ require 'infinity_test/framework/rust_cargo'
77
+ require 'infinity_test/framework/rocket'
68
78
  require 'infinity_test/test_framework/test_unit'
69
79
  require 'infinity_test/test_framework/rspec'
80
+ require 'infinity_test/test_framework/ex_unit'
81
+ require 'infinity_test/test_framework/pytest'
82
+ require 'infinity_test/test_framework/cargo_test'
@@ -20,6 +20,9 @@ module InfinityTest
20
20
  before do
21
21
  base.strategy = :auto_discover
22
22
  allow(Strategy::RubyDefault).to receive(:run?).and_return(false)
23
+ allow(Strategy::ElixirDefault).to receive(:run?).and_return(false)
24
+ allow(Strategy::PythonDefault).to receive(:run?).and_return(false)
25
+ allow(Strategy::RustDefault).to receive(:run?).and_return(false)
23
26
  expect(Strategy::Rvm).to receive(:run?).and_return(true)
24
27
  end
25
28
 
@@ -44,6 +47,9 @@ module InfinityTest
44
47
  allow(Strategy::RubyDefault).to receive(:run?).and_return(false)
45
48
  expect(Strategy::Rvm).to receive(:run?).and_return(false)
46
49
  allow(Strategy::Rbenv).to receive(:run?).and_return(false)
50
+ allow(Strategy::ElixirDefault).to receive(:run?).and_return(false)
51
+ allow(Strategy::PythonDefault).to receive(:run?).and_return(false)
52
+ allow(Strategy::RustDefault).to receive(:run?).and_return(false)
47
53
  end
48
54
 
49
55
  it 'raises exception' do
@@ -57,6 +63,13 @@ module InfinityTest
57
63
  before do
58
64
  base.framework = :auto_discover
59
65
  allow(Framework::Rubygems).to receive(:run?).and_return(false)
66
+ allow(Framework::ElixirMix).to receive(:run?).and_return(false)
67
+ allow(Framework::Phoenix).to receive(:run?).and_return(false)
68
+ allow(Framework::Django).to receive(:run?).and_return(false)
69
+ allow(Framework::FastApi).to receive(:run?).and_return(false)
70
+ allow(Framework::PythonPackage).to receive(:run?).and_return(false)
71
+ allow(Framework::Rocket).to receive(:run?).and_return(false)
72
+ allow(Framework::RustCargo).to receive(:run?).and_return(false)
60
73
  expect(Framework::Rails).to receive(:run?).and_return(true)
61
74
  end
62
75
 
@@ -81,6 +94,9 @@ module InfinityTest
81
94
  before do
82
95
  base.test_framework = :auto_discover
83
96
  allow(TestFramework::TestUnit).to receive(:run?).and_return(false)
97
+ allow(TestFramework::ExUnit).to receive(:run?).and_return(false)
98
+ allow(TestFramework::Pytest).to receive(:run?).and_return(false)
99
+ allow(TestFramework::CargoTest).to receive(:run?).and_return(false)
84
100
  expect(TestFramework::Rspec).to receive(:run?).and_return(true)
85
101
  end
86
102
 
@@ -102,15 +118,15 @@ module InfinityTest
102
118
 
103
119
  describe 'PRIORITY' do
104
120
  it 'defines priority order for strategies' do
105
- expect(AutoDiscover::PRIORITY[:strategy]).to eq [:rvm, :rbenv, :ruby_default]
121
+ expect(AutoDiscover::PRIORITY[:strategy]).to eq [:rvm, :rbenv, :elixir_default, :python_default, :rust_default, :ruby_default]
106
122
  end
107
123
 
108
124
  it 'defines priority order for frameworks' do
109
- expect(AutoDiscover::PRIORITY[:framework]).to eq [:rails, :padrino, :rubygems]
125
+ expect(AutoDiscover::PRIORITY[:framework]).to eq [:rails, :padrino, :phoenix, :elixir_mix, :django, :fast_api, :python_package, :rocket, :rust_cargo, :rubygems]
110
126
  end
111
127
 
112
128
  it 'defines priority order for test frameworks' do
113
- expect(AutoDiscover::PRIORITY[:test_framework]).to eq [:rspec, :test_unit]
129
+ expect(AutoDiscover::PRIORITY[:test_framework]).to eq [:rspec, :test_unit, :ex_unit, :pytest, :cargo_test]
114
130
  end
115
131
  end
116
132
 
@@ -121,6 +137,9 @@ module InfinityTest
121
137
  # Both RVM and RubyDefault would match, but RVM has higher priority
122
138
  allow(Strategy::Rvm).to receive(:run?).and_return(true)
123
139
  allow(Strategy::Rbenv).to receive(:run?).and_return(false)
140
+ allow(Strategy::ElixirDefault).to receive(:run?).and_return(false)
141
+ allow(Strategy::PythonDefault).to receive(:run?).and_return(false)
142
+ allow(Strategy::RustDefault).to receive(:run?).and_return(false)
124
143
  allow(Strategy::RubyDefault).to receive(:run?).and_return(true)
125
144
  end
126
145
 
@@ -136,6 +155,13 @@ module InfinityTest
136
155
  # Both Rails and Rubygems would match, but Rails has higher priority
137
156
  allow(Framework::Rails).to receive(:run?).and_return(true)
138
157
  allow(Framework::Padrino).to receive(:run?).and_return(false)
158
+ allow(Framework::Phoenix).to receive(:run?).and_return(false)
159
+ allow(Framework::ElixirMix).to receive(:run?).and_return(false)
160
+ allow(Framework::Django).to receive(:run?).and_return(false)
161
+ allow(Framework::FastApi).to receive(:run?).and_return(false)
162
+ allow(Framework::PythonPackage).to receive(:run?).and_return(false)
163
+ allow(Framework::Rocket).to receive(:run?).and_return(false)
164
+ allow(Framework::RustCargo).to receive(:run?).and_return(false)
139
165
  allow(Framework::Rubygems).to receive(:run?).and_return(true)
140
166
  end
141
167
 
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ module InfinityTest
4
+ module Framework
5
+ describe Django do
6
+ let(:observer) { double('Observer') }
7
+ let(:test_framework) { double('TestFramework', test_dir: 'tests', test_helper_file: 'tests/conftest.py') }
8
+ let(:continuous_test_server) { double('ContinuousTestServer', observer: observer, test_framework: test_framework) }
9
+ subject { Django.new(continuous_test_server) }
10
+
11
+ describe "#heuristics" do
12
+ before do
13
+ allow(subject).to receive(:watch_django_apps)
14
+ allow(File).to receive(:directory?).with('tests').and_return(true)
15
+ allow(File).to receive(:exist?).with('tests/conftest.py').and_return(true)
16
+ end
17
+
18
+ it "adds heuristics for django apps, test, and conftest" do
19
+ expect(subject).to receive(:watch_django_apps)
20
+ expect(observer).to receive(:watch_dir).with('tests', :py)
21
+ expect(observer).to receive(:watch).with('tests/conftest.py')
22
+ expect { subject.heuristics }.to_not raise_exception
23
+ end
24
+ end
25
+
26
+ describe "#heuristics!" do
27
+ it "appends .py extension to hike" do
28
+ hike = double('Hike')
29
+ allow(subject).to receive(:hike).and_return(hike)
30
+ expect(hike).to receive(:append_extension).with('.py')
31
+ expect(hike).to receive(:append_path).with('tests')
32
+ allow(subject).to receive(:heuristics)
33
+ subject.heuristics!
34
+ end
35
+ end
36
+
37
+ describe "#watch_django_apps" do
38
+ context "when Django apps exist" do
39
+ before do
40
+ allow(Dir).to receive(:glob).with('*').and_return(['myapp', 'accounts', 'tests'])
41
+ allow(File).to receive(:directory?).with('myapp').and_return(true)
42
+ allow(File).to receive(:directory?).with('accounts').and_return(true)
43
+ allow(File).to receive(:directory?).with('tests').and_return(true)
44
+ allow(File).to receive(:exist?).with('myapp/models.py').and_return(true)
45
+ allow(File).to receive(:exist?).with('myapp/views.py').and_return(false)
46
+ allow(File).to receive(:exist?).with('myapp/apps.py').and_return(false)
47
+ allow(File).to receive(:exist?).with('accounts/models.py').and_return(false)
48
+ allow(File).to receive(:exist?).with('accounts/views.py').and_return(true)
49
+ allow(File).to receive(:exist?).with('accounts/apps.py').and_return(false)
50
+ end
51
+
52
+ it "watches Django app directories" do
53
+ expect(observer).to receive(:watch_dir).with('myapp', :py)
54
+ expect(observer).to receive(:watch_dir).with('accounts', :py)
55
+ subject.watch_django_apps
56
+ end
57
+ end
58
+ end
59
+
60
+ describe ".run?" do
61
+ context "when manage.py exists with Django" do
62
+ before do
63
+ allow(File).to receive(:exist?).with('manage.py').and_return(true)
64
+ allow(File).to receive(:read).with('manage.py').and_return("os.environ.setdefault('DJANGO_SETTINGS_MODULE'")
65
+ end
66
+
67
+ it "returns true" do
68
+ expect(Django).to be_run
69
+ end
70
+ end
71
+
72
+ context "when manage.py does not exist" do
73
+ before do
74
+ allow(File).to receive(:exist?).with('manage.py').and_return(false)
75
+ end
76
+
77
+ it "returns false" do
78
+ expect(Django).not_to be_run
79
+ end
80
+ end
81
+
82
+ context "when manage.py exists but is not Django" do
83
+ before do
84
+ allow(File).to receive(:exist?).with('manage.py').and_return(true)
85
+ allow(File).to receive(:read).with('manage.py').and_return("print('hello')")
86
+ end
87
+
88
+ it "returns false" do
89
+ expect(Django).not_to be_run
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ module InfinityTest
4
+ module Framework
5
+ describe ElixirMix do
6
+ let(:observer) { double('Observer') }
7
+ let(:test_framework) { double('TestFramework', test_dir: 'test', test_helper_file: 'test/test_helper.exs') }
8
+ let(:continuous_test_server) { double('ContinuousTestServer', observer: observer, test_framework: test_framework) }
9
+ subject { ElixirMix.new(continuous_test_server) }
10
+
11
+ describe "#heuristics" do
12
+ it "adds heuristics for lib, test, and test_helper" do
13
+ expect(observer).to receive(:watch_dir).with(:lib, :ex)
14
+ expect(observer).to receive(:watch_dir).with('test', :exs)
15
+ expect(observer).to receive(:watch).with('test/test_helper.exs')
16
+ expect { subject.heuristics }.to_not raise_exception
17
+ end
18
+ end
19
+
20
+ describe "#heuristics!" do
21
+ it "appends .exs extension to hike" do
22
+ hike = double('Hike')
23
+ allow(subject).to receive(:hike).and_return(hike)
24
+ expect(hike).to receive(:append_extension).with('.exs')
25
+ expect(hike).to receive(:append_path).with('test')
26
+ allow(subject).to receive(:heuristics)
27
+ subject.heuristics!
28
+ end
29
+ end
30
+
31
+ describe ".run?" do
32
+ it "returns true if there is a mix.exs in the user current dir" do
33
+ expect(File).to receive(:exist?).with('mix.exs').and_return(true)
34
+ expect(ElixirMix).to be_run
35
+ end
36
+
37
+ it "returns false if there is no mix.exs in the user current dir" do
38
+ expect(File).to receive(:exist?).with('mix.exs').and_return(false)
39
+ expect(ElixirMix).not_to be_run
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ module InfinityTest
4
+ module Framework
5
+ describe FastApi do
6
+ let(:observer) { double('Observer') }
7
+ let(:test_framework) { double('TestFramework', test_dir: 'tests', test_helper_file: 'tests/conftest.py') }
8
+ let(:continuous_test_server) { double('ContinuousTestServer', observer: observer, test_framework: test_framework) }
9
+ subject { FastApi.new(continuous_test_server) }
10
+
11
+ describe "#heuristics" do
12
+ before do
13
+ allow(subject).to receive(:watch_fastapi_dirs)
14
+ allow(File).to receive(:exist?).with('tests/conftest.py').and_return(true)
15
+ end
16
+
17
+ it "adds heuristics for fastapi dirs, test, and conftest" do
18
+ expect(subject).to receive(:watch_fastapi_dirs)
19
+ expect(observer).to receive(:watch_dir).with('tests', :py)
20
+ expect(observer).to receive(:watch).with('tests/conftest.py')
21
+ expect { subject.heuristics }.to_not raise_exception
22
+ end
23
+ end
24
+
25
+ describe "#heuristics!" do
26
+ it "appends .py extension to hike" do
27
+ hike = double('Hike')
28
+ allow(subject).to receive(:hike).and_return(hike)
29
+ expect(hike).to receive(:append_extension).with('.py')
30
+ expect(hike).to receive(:append_path).with('tests')
31
+ allow(subject).to receive(:heuristics)
32
+ subject.heuristics!
33
+ end
34
+ end
35
+
36
+ describe "#watch_fastapi_dirs" do
37
+ context "when app directory exists" do
38
+ before do
39
+ allow(File).to receive(:directory?).with('app').and_return(true)
40
+ allow(File).to receive(:directory?).with('src').and_return(false)
41
+ allow(File).to receive(:directory?).with('routers').and_return(false)
42
+ allow(File).to receive(:directory?).with('api').and_return(false)
43
+ allow(File).to receive(:directory?).with('endpoints').and_return(false)
44
+ allow(File).to receive(:directory?).with('.').and_return(true)
45
+ allow(Dir).to receive(:glob).with('*.py').and_return(['main.py'])
46
+ allow(Dir).to receive(:glob).with('app/**/*.py').and_return(['app/main.py'])
47
+ allow(Dir).to receive(:glob).with('./**/*.py').and_return(['main.py'])
48
+ end
49
+
50
+ it "watches the app directory" do
51
+ expect(observer).to receive(:watch_dir).with('app', :py)
52
+ expect(observer).to receive(:watch_dir).with('.', :py)
53
+ subject.watch_fastapi_dirs
54
+ end
55
+ end
56
+ end
57
+
58
+ describe ".run?" do
59
+ context "when app/main.py exists with FastAPI" do
60
+ before do
61
+ allow(File).to receive(:exist?).with('app/main.py').and_return(true)
62
+ allow(File).to receive(:read).with('app/main.py').and_return('from fastapi import FastAPI')
63
+ end
64
+
65
+ it "returns true" do
66
+ expect(FastApi).to be_run
67
+ end
68
+ end
69
+
70
+ context "when main.py exists with FastAPI" do
71
+ before do
72
+ allow(File).to receive(:exist?).with('app/main.py').and_return(false)
73
+ allow(File).to receive(:exist?).with('main.py').and_return(true)
74
+ allow(File).to receive(:read).with('main.py').and_return('app = FastAPI()')
75
+ end
76
+
77
+ it "returns true" do
78
+ expect(FastApi).to be_run
79
+ end
80
+ end
81
+
82
+ context "when no FastAPI project" do
83
+ before do
84
+ allow(File).to receive(:exist?).with('app/main.py').and_return(false)
85
+ allow(File).to receive(:exist?).with('main.py').and_return(false)
86
+ allow(File).to receive(:exist?).with('src/main.py').and_return(false)
87
+ end
88
+
89
+ it "returns false" do
90
+ expect(FastApi).not_to be_run
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -4,18 +4,40 @@ module InfinityTest
4
4
  module Framework
5
5
  describe Padrino do
6
6
  let(:observer) { double('Observer') }
7
- let(:test_framework) { double('TestFramework') }
7
+ let(:test_framework) { double('TestFramework', test_dir: 'spec') }
8
8
  let(:continuous_test_server) { double('ContinuousTestServer', observer: observer, test_framework: test_framework) }
9
9
  subject { Padrino.new(continuous_test_server) }
10
10
 
11
11
  describe "#heuristics" do
12
- it "adds heuristics" do
13
- # 6 watch_dir calls: models, controllers, helpers, mailers, lib, test_dir
14
- expect(observer).to receive(:watch_dir).exactly(6)
15
- # 1 watch call for test_helper_file
12
+ it "watches lib, test_dir, and test_helper_file" do
13
+ allow(File).to receive(:directory?).with('app').and_return(false)
14
+
15
+ expect(observer).to receive(:watch_dir).with(:lib)
16
+ expect(observer).to receive(:watch_dir).with('spec')
16
17
  expect(observer).to receive(:watch)
17
18
  expect(test_framework).to receive(:test_helper_file)
18
- expect(test_framework).to receive(:test_dir)
19
+
20
+ expect { subject.heuristics }.to_not raise_exception
21
+ end
22
+
23
+ it "auto-discovers app directories containing ruby files" do
24
+ allow(File).to receive(:directory?).with('app').and_return(true)
25
+ allow(Dir).to receive(:glob).with('app/*').and_return(['app/models', 'app/views', 'app/components'])
26
+ allow(File).to receive(:directory?).with('app/models').and_return(true)
27
+ allow(File).to receive(:directory?).with('app/views').and_return(true)
28
+ allow(File).to receive(:directory?).with('app/components').and_return(true)
29
+ allow(Dir).to receive(:glob).with('app/models/**/*.rb').and_return(['app/models/user.rb'])
30
+ allow(Dir).to receive(:glob).with('app/views/**/*.rb').and_return([])
31
+ allow(Dir).to receive(:glob).with('app/components/**/*.rb').and_return(['app/components/button.rb'])
32
+
33
+ # Should watch models and components (have .rb files), skip views (no .rb files)
34
+ expect(observer).to receive(:watch_dir).with('app/models')
35
+ expect(observer).to receive(:watch_dir).with('app/components')
36
+ expect(observer).to receive(:watch_dir).with(:lib)
37
+ expect(observer).to receive(:watch_dir).with('spec')
38
+ expect(observer).to receive(:watch)
39
+ expect(test_framework).to receive(:test_helper_file)
40
+
19
41
  expect { subject.heuristics }.to_not raise_exception
20
42
  end
21
43
  end