polytrix 0.0.1 → 0.1.0.pre

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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.rspec +1 -6
  4. data/.rubocop-todo.yml +19 -0
  5. data/.rubocop.yml +10 -0
  6. data/.travis.yml +11 -0
  7. data/Gemfile +0 -16
  8. data/README.md +119 -28
  9. data/Rakefile +18 -123
  10. data/bin/polytrix +5 -0
  11. data/doc-src/_markdown.md +5 -0
  12. data/doc-src/default_bootstrap.md +13 -0
  13. data/docs/influences.md +28 -0
  14. data/docs/samples/code2doc/java/HelloWorld.md +13 -0
  15. data/docs/samples/code2doc/java/Quine.md +33 -0
  16. data/docs/samples/code2doc/python/hello_world.md +3 -0
  17. data/docs/samples/code2doc/python/quine.md +4 -0
  18. data/docs/samples/code2doc/ruby/hello_world.md +7 -0
  19. data/features/execution.feature +67 -0
  20. data/features/fixtures/configs/empty.yml +12 -0
  21. data/features/fixtures/configs/hello_world.yml +10 -0
  22. data/features/fixtures/spec/polytrix_merge.rb +5 -0
  23. data/features/fixtures/spec/polytrix_spec.rb +10 -0
  24. data/features/reporting.feature +140 -0
  25. data/features/step_definitions/sdk_steps.rb +12 -0
  26. data/features/support/env.rb +8 -0
  27. data/lib/polytrix/challenge.rb +20 -7
  28. data/lib/polytrix/challenge_runner.rb +9 -44
  29. data/lib/polytrix/cli/add.rb +67 -0
  30. data/lib/polytrix/cli/report.rb +88 -0
  31. data/lib/polytrix/cli/reports/hash_reporter.rb +30 -0
  32. data/lib/polytrix/cli/reports/json_reporter.rb +14 -0
  33. data/lib/polytrix/cli/reports/markdown_reporter.rb +23 -0
  34. data/lib/polytrix/cli/reports/yaml_reporter.rb +14 -0
  35. data/lib/polytrix/cli.rb +158 -0
  36. data/lib/polytrix/configuration.rb +65 -4
  37. data/lib/polytrix/core/file_system_helper.rb +75 -0
  38. data/lib/polytrix/core/implementor.rb +31 -3
  39. data/lib/polytrix/documentation/code_segmenter.rb +168 -0
  40. data/lib/polytrix/documentation/comment_styles.rb +87 -0
  41. data/lib/polytrix/documentation/helpers/code_helper.rb +85 -0
  42. data/lib/polytrix/documentation/view_helper.rb +21 -0
  43. data/lib/polytrix/documentation_generator.rb +59 -10
  44. data/lib/polytrix/executor.rb +89 -0
  45. data/lib/polytrix/logger.rb +17 -0
  46. data/lib/polytrix/manifest.rb +64 -7
  47. data/lib/polytrix/result.rb +16 -2
  48. data/lib/polytrix/rspec/documentation_formatter.rb +41 -16
  49. data/lib/polytrix/rspec/yaml_report.rb +51 -0
  50. data/lib/polytrix/rspec.rb +32 -53
  51. data/lib/polytrix/runners/middleware/feature_executor.rb +4 -3
  52. data/lib/polytrix/runners/middleware/setup_env_vars.rb +6 -4
  53. data/lib/polytrix/validation.rb +20 -0
  54. data/lib/polytrix/validations.rb +23 -0
  55. data/lib/polytrix/validator.rb +20 -0
  56. data/lib/polytrix/validator_registry.rb +34 -0
  57. data/lib/polytrix/version.rb +1 -1
  58. data/lib/polytrix.rb +125 -22
  59. data/polytrix.gemspec +7 -2
  60. data/polytrix.rb +6 -0
  61. data/polytrix_tests.yml +20 -0
  62. data/resources/code_sample.tt +2 -0
  63. data/samples/.gitignore +2 -0
  64. data/samples/_markdown.md +5 -0
  65. data/samples/default_bootstrap.rb +14 -0
  66. data/samples/polytrix.rb +28 -0
  67. data/samples/polytrix_cli.sh +7 -0
  68. data/samples/polytrix_tests.yml +10 -0
  69. data/{sdks/fog → samples}/scripts/bootstrap +0 -2
  70. data/samples/scripts/wrapper +7 -0
  71. data/samples/sdks/custom/polytrix.yml +2 -0
  72. data/samples/sdks/java/.gitignore +2 -0
  73. data/samples/sdks/java/build.gradle +14 -0
  74. data/samples/sdks/java/challenges/HelloWorld.java +10 -0
  75. data/samples/sdks/java/challenges/Quine.java +31 -0
  76. data/samples/sdks/java/code_sample.tt +11 -0
  77. data/samples/sdks/java/scripts/bootstrap +2 -0
  78. data/samples/sdks/java/scripts/wrapper +8 -0
  79. data/samples/sdks/python/challenges/hello_world.py +2 -0
  80. data/samples/sdks/python/challenges/quine.py +2 -0
  81. data/{sdks/pkgcloud → samples/sdks/python}/scripts/wrapper +1 -1
  82. data/samples/sdks/ruby/challenges/hello_world.rb +4 -0
  83. data/scripts/bootstrap +1 -9
  84. data/scripts/wrapper +7 -0
  85. data/spec/fabricators/challenge_fabricator.rb +17 -0
  86. data/spec/fabricators/manifest_fabricator.rb +50 -0
  87. data/spec/fabricators/validator_fabricator.rb +12 -0
  88. data/spec/fixtures/{polytrix.yml → polytrix_tests.yml} +0 -0
  89. data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
  90. data/spec/polytrix/challenge_runner_spec.rb +3 -3
  91. data/spec/polytrix/challenge_spec.rb +3 -4
  92. data/spec/polytrix/cli_spec.rb +39 -0
  93. data/spec/polytrix/configuration_spec.rb +45 -1
  94. data/spec/polytrix/documentation/helpers/code_helper_spec.rb +120 -0
  95. data/spec/polytrix/documentation_generator_spec.rb +41 -20
  96. data/spec/polytrix/file_finder_spec.rb +4 -3
  97. data/spec/polytrix/implementor_spec.rb +33 -0
  98. data/spec/polytrix/manifest_spec.rb +32 -14
  99. data/spec/polytrix/middleware/feature_executor_spec.rb +1 -1
  100. data/spec/polytrix/result_spec.rb +49 -0
  101. data/spec/polytrix/validations_spec.rb +16 -0
  102. data/spec/polytrix/validator_registry_spec.rb +39 -0
  103. data/spec/polytrix/validator_spec.rb +63 -0
  104. data/spec/polytrix_spec.rb +33 -7
  105. data/spec/spec_helper.rb +14 -1
  106. data/spec/thor_spy.rb +64 -0
  107. metadata +177 -160
  108. data/.rspec_parallel +0 -10
  109. data/Vagrantfile +0 -41
  110. data/features/0_identity_spec.rb +0 -40
  111. data/features/1_cloud_files_spec.rb +0 -48
  112. data/features/2_servers_spec.rb +0 -19
  113. data/features/features_helper.rb +0 -46
  114. data/features/helpers/cloudfiles_helper.rb +0 -31
  115. data/features/helpers/pacto_helper.rb +0 -33
  116. data/features/helpers/teardown_helper.rb +0 -49
  117. data/features/pacto/extensions/loaders/api_blueprint_loader.rb +0 -63
  118. data/features/pacto/extensions/loaders/simple_loader.rb +0 -55
  119. data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +0 -17
  120. data/features/pacto/extensions/matchers.rb +0 -38
  121. data/features/phase2/feature_coverage_report.rb +0 -109
  122. data/features/phase2/run_all_features.rb +0 -14
  123. data/features/static_site/fixtures/index.html +0 -6
  124. data/lib/polytrix/challenge_builder.rb +0 -16
  125. data/lib/polytrix/core/file_finder.rb +0 -43
  126. data/lib/polytrix/core/result_tracker.rb +0 -25
  127. data/lib/polytrix/runners/middleware/pacto.rb +0 -59
  128. data/packer/.gitignore +0 -3
  129. data/packer/Berksfile +0 -15
  130. data/packer/Gemfile +0 -5
  131. data/packer/Vagrantfile +0 -128
  132. data/packer/cookbooks/drg/metadata.rb +0 -27
  133. data/packer/cookbooks/drg/recipes/admins.rb +0 -22
  134. data/packer/cookbooks/drg/recipes/default.rb +0 -9
  135. data/packer/cookbooks/drg/recipes/dotnet.rb +0 -4
  136. data/packer/cookbooks/drg/recipes/golang.rb +0 -4
  137. data/packer/cookbooks/drg/recipes/java.rb +0 -5
  138. data/packer/cookbooks/drg/recipes/php.rb +0 -10
  139. data/packer/cookbooks/drg/recipes/ruby.rb +0 -29
  140. data/packer/cookbooks/drg/recipes/system.rb +0 -13
  141. data/packer/create_box.sh +0 -10
  142. data/packer/http/preseed.cfg +0 -87
  143. data/packer/packer.json +0 -91
  144. data/packer/scripts/root_setup.sh +0 -37
  145. data/packer/scripts/setup.sh +0 -32
  146. data/pacto/config/pacto_server.rb +0 -40
  147. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +0 -64
  148. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +0 -100
  149. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +0 -176
  150. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +0 -189
  151. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +0 -63
  152. data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +0 -62
  153. data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +0 -192
  154. data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +0 -39
  155. data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +0 -38
  156. data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +0 -30
  157. data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +0 -30
  158. data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +0 -114
  159. data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +0 -13
  160. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +0 -46
  161. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +0 -230
  162. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +0 -15
  163. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +0 -43
  164. data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +0 -44
  165. data/pacto/pacto_server.rb +0 -100
  166. data/pacto/rackspace_uri_map.yaml +0 -229
  167. data/scripts/cibuild +0 -4
  168. data/sdks/fog/.gitignore +0 -1
  169. data/sdks/fog/Gemfile +0 -5
  170. data/sdks/fog/challenges/all_connections.rb +0 -45
  171. data/sdks/fog/challenges/authenticate_token.rb +0 -15
  172. data/sdks/fog/challenges/cdn_enable_container.rb +0 -20
  173. data/sdks/fog/challenges/create_a_container.rb +0 -17
  174. data/sdks/fog/challenges/create_server.rb +0 -36
  175. data/sdks/fog/challenges/get_object_metadata.rb +0 -13
  176. data/sdks/fog/challenges/list_containers.rb +0 -10
  177. data/sdks/fog/challenges/provision_scalable_webapp.rb +0 -30
  178. data/sdks/fog/challenges/upload_folder.rb +0 -25
  179. data/sdks/fog/scripts/bootstrap.ps1 +0 -1
  180. data/sdks/fog/scripts/wrapper +0 -2
  181. data/sdks/fog/scripts/wrapper.ps1 +0 -1
  182. data/sdks/gophercloud/.gitignore +0 -2
  183. data/sdks/gophercloud/challenges/authenticate_token.go +0 -23
  184. data/sdks/gophercloud/scripts/bootstrap +0 -6
  185. data/sdks/gophercloud/scripts/wrapper +0 -10
  186. data/sdks/jclouds/.gitignore +0 -1
  187. data/sdks/jclouds/challenges/AuthenticateToken.java +0 -115
  188. data/sdks/jclouds/pom.xml +0 -34
  189. data/sdks/jclouds/scripts/bootstrap +0 -3
  190. data/sdks/jclouds/scripts/wrapper +0 -7
  191. data/sdks/openstack.net/.gitignore +0 -4
  192. data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
  193. data/sdks/openstack.net/.nuget/NuGet.Config +0 -6
  194. data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
  195. data/sdks/openstack.net/.nuget/NuGet.targets +0 -136
  196. data/sdks/openstack.net/Challenge.cs +0 -10
  197. data/sdks/openstack.net/RunChallenge.cs +0 -19
  198. data/sdks/openstack.net/challenges/AuthenticateToken.cs +0 -24
  199. data/sdks/openstack.net/challenges/Weird.cs +0 -133
  200. data/sdks/openstack.net/openstack.net.csproj +0 -58
  201. data/sdks/openstack.net/openstack.net.sln +0 -27
  202. data/sdks/openstack.net/openstack.net.userprefs +0 -8
  203. data/sdks/openstack.net/packages.config +0 -6
  204. data/sdks/openstack.net/scripts/bootstrap +0 -2
  205. data/sdks/openstack.net/scripts/bootstrap.ps1 +0 -2
  206. data/sdks/openstack.net/scripts/wrapper +0 -7
  207. data/sdks/openstack.net/scripts/wrapper.ps1 +0 -1
  208. data/sdks/php-opencloud/.gitignore +0 -4
  209. data/sdks/php-opencloud/challenges/all_connections.php +0 -64
  210. data/sdks/php-opencloud/challenges/authenticate_token.php +0 -14
  211. data/sdks/php-opencloud/challenges/create_server.php +0 -39
  212. data/sdks/php-opencloud/challenges/get_object_metadata.php +0 -19
  213. data/sdks/php-opencloud/composer.json +0 -5
  214. data/sdks/php-opencloud/scripts/bootstrap +0 -4
  215. data/sdks/php-opencloud/scripts/bootstrap.ps1 +0 -2
  216. data/sdks/php-opencloud/scripts/wrapper +0 -2
  217. data/sdks/php-opencloud/scripts/wrapper.ps1 +0 -1
  218. data/sdks/pkgcloud/.gitignore +0 -1
  219. data/sdks/pkgcloud/challenges/authenticate_token.js +0 -17
  220. data/sdks/pkgcloud/challenges/get_object_metadata.js +0 -18
  221. data/sdks/pkgcloud/scripts/bootstrap +0 -2
  222. data/sdks/pkgcloud/scripts/bootstrap.ps1 +0 -1
  223. data/sdks/pkgcloud/scripts/wrapper.ps1 +0 -1
  224. data/sdks/pyrax/.gitignore +0 -2
  225. data/sdks/pyrax/challenges/all_connections.py +0 -61
  226. data/sdks/pyrax/challenges/authenticate_token.py +0 -17
  227. data/sdks/pyrax/challenges/cdn_enable_container.py +0 -22
  228. data/sdks/pyrax/challenges/create_a_container.py +0 -21
  229. data/sdks/pyrax/challenges/create_server.py +0 -35
  230. data/sdks/pyrax/challenges/get_object_metadata.py +0 -17
  231. data/sdks/pyrax/challenges/upload_folder.py +0 -32
  232. data/sdks/pyrax/requirements.txt +0 -21
  233. data/sdks/pyrax/scripts/bootstrap +0 -9
  234. data/sdks/pyrax/scripts/bootstrap.ps1 +0 -7
  235. data/sdks/pyrax/scripts/wrapper +0 -3
  236. data/sdks/pyrax/scripts/wrapper.ps1 +0 -2
  237. data/spec/polytrix/challenge_builder_spec.rb +0 -16
  238. data/spec/rspec_spec.rb +0 -17
@@ -0,0 +1,50 @@
1
+ require 'hashie/mash'
2
+
3
+ # Fabricates test manifests (.polytrix_tests.yml files)
4
+ LANGUAGES = %w(java ruby python nodejs c# golang php)
5
+ SAMPLE_NAMES = [
6
+ 'hello world',
7
+ 'quine',
8
+ 'my_kata'
9
+ ]
10
+
11
+ Fabricator(:manifest, from: Polytrix::Manifest) do
12
+ initialize_with { @_klass.new to_hash } # Hash based initialization
13
+ transient suite_count: 3
14
+ transient samples_per_suite: 3
15
+ global_env do
16
+ {
17
+ VAR1: 1,
18
+ VAR2: 2
19
+ }
20
+ end
21
+ suites do |attr|
22
+ suite_count = attr[:suite_count]
23
+ if suite_count
24
+ suites = attr[:suite_count].times.reduce({}) do |h, i|
25
+ name = LANGUAGES[i] ||= "suite_#{i}"
26
+ h[name] = Fabricate(:suite, name: name, sample_count: attr[:samples_per_suite])
27
+ h
28
+ end
29
+ suites
30
+ else
31
+ nil
32
+ end
33
+ end
34
+ end
35
+
36
+ Fabricator(:suite, from: Hashie::Mash) do
37
+ initialize_with { @_klass.new to_hash } # Hash based initialization
38
+ transient name: LANGUAGES[0]
39
+ transient sample_count: 3
40
+ samples do |attr|
41
+ sample_count = attr[:sample_count]
42
+ if sample_count
43
+ attr[:sample_count].times.map do |i|
44
+ SAMPLE_NAMES[i] ||= "sample_#{i}"
45
+ end
46
+ else
47
+ nil
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ require 'hashie/mash'
2
+
3
+ Fabricator(:validator, from: Polytrix::Validator) do
4
+ initialize_with do
5
+ callback = @_transient_attributes.delete :callback
6
+ scope = @_transient_attributes
7
+ @_klass.new(scope, &callback)
8
+ end # Hash based initialization
9
+ transient suite: LANGUAGES.sample
10
+ transient sample: SAMPLE_NAMES.sample
11
+ transient callback: Proc.new { Proc.new { |challenge| } } # rubocop:disable Proc
12
+ end
File without changes
@@ -0,0 +1 @@
1
+ I am a generic template that is being used for the <%= scenario %> scenario.
@@ -1,8 +1,8 @@
1
1
  module Polytrix
2
2
  describe ChallengeRunner do
3
- subject(:runner) { ChallengeRunner.createRunner }
3
+ subject(:runner) { ChallengeRunner.create_runner }
4
4
  let(:challenge) do
5
- Challenge.new :name => 'factorial', :source_file => 'spec/fixtures/factorial.py', :basedir => 'spec/fixtures'
5
+ Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures')
6
6
  end
7
7
 
8
8
  describe '#run_challenge' do
@@ -11,4 +11,4 @@ module Polytrix
11
11
  end
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -1,9 +1,8 @@
1
1
  module Polytrix
2
2
  describe Challenge do
3
3
  subject(:challenge) do
4
- implementor = Polytrix::Implementor.new :name => 'some_sdk', :basedir => 'spec/fixtures'
5
- builder = Polytrix::ChallengeBuilder.new implementor
6
- builder.build :name => 'factorial', :vars => {}
4
+ implementor = Polytrix::Implementor.new name: 'some_sdk', basedir: 'spec/fixtures'
5
+ implementor.build_challenge name: 'factorial', vars: {}
7
6
  end
8
7
 
9
8
  describe '#run' do
@@ -17,4 +16,4 @@ module Polytrix
17
16
  end
18
17
  end
19
18
  end
20
- end
19
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'polytrix/cli'
3
+
4
+ module Polytrix
5
+ module CLI
6
+ describe Main do
7
+ let(:kernel) { double(:kernel) }
8
+ subject { ThorSpy.on(described_class, kernel) }
9
+ describe 'bootstrap' do
10
+ context 'with no args' do
11
+ it 'calls Polytrix.bootstrap' do
12
+ expect(kernel).to receive(:exit).with(0)
13
+ expect(Polytrix).to receive(:bootstrap)
14
+ subject.bootstrap
15
+ end
16
+ end
17
+
18
+ context 'with an existing SDK' do
19
+ before do
20
+ @implementor = Polytrix.configuration.implementor name: 'test', basedir: '.'
21
+ end
22
+
23
+ it 'calls bootstrap on the SDK' do
24
+ expect(@implementor).to receive(:bootstrap)
25
+ expect(kernel).to receive(:exit).with(0)
26
+ expect(subject.stderr.string).to eq('')
27
+ subject.bootstrap('test')
28
+ end
29
+ end
30
+
31
+ context 'with an non-existant SDK' do
32
+ it 'fails' do
33
+ expect { subject.bootstrap('missing') }.to raise_error(SystemExit, 'SDK missing not found')
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -3,8 +3,52 @@ module Polytrix
3
3
  subject(:configuration) { Configuration.new }
4
4
 
5
5
  it 'creates a logger' do
6
- expect(configuration.logger).to be_kind_of Logger
6
+ expect(configuration.logger).to be_kind_of ::Logger
7
7
  end
8
8
 
9
+ describe '.test_manifest' do
10
+ it 'parses the YAML file and registers the manifest' do
11
+ original_manifest = configuration.test_manifest
12
+ configuration.test_manifest = 'spec/fixtures/polytrix_tests.yml'
13
+ new_manifest = configuration.test_manifest
14
+ expect(original_manifest).to_not eq(new_manifest)
15
+ expect(new_manifest).to(be_an_instance_of(Polytrix::Manifest))
16
+ end
17
+ end
18
+
19
+ describe '.implementor' do
20
+ context 'argument is a Hash' do
21
+ it 'creates and registers Implementors' do
22
+ # This'd be a bit nicer w/ rspec 3...
23
+ expect do
24
+ configuration.implementor name: 'test', basedir: '.'
25
+ end.to change {
26
+ configuration.implementors
27
+ }.from(be_empty).to be_an_instance_of(Array)
28
+
29
+ expect(configuration.implementors.first).to be_an_instance_of Polytrix::Implementor
30
+ expect(configuration.implementors.first.name).to eq('test')
31
+ end
32
+ end
33
+ context 'argument is a String' do
34
+ context 'directory exists' do
35
+ context 'polytrix.yml does not exist' do
36
+ it 'builds an implementor with default settings' do
37
+ implementor = configuration.implementor('samples/sdks/ruby')
38
+ expect(implementor).to be_an_instance_of(Polytrix::Implementor)
39
+ expect(implementor.name).to eq('ruby') # directory name
40
+ end
41
+ end
42
+
43
+ context 'polytrix_tests.yml exists' do
44
+ it 'loads settings from polytrix.yml' do
45
+ implementor = configuration.implementor('samples/sdks/custom')
46
+ expect(implementor).to be_an_instance_of(Polytrix::Implementor)
47
+ expect(implementor.name).to eq('My Custom project')
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
9
53
  end
10
54
  end
@@ -0,0 +1,120 @@
1
+ module Polytrix
2
+ module Documentation
3
+ module Helpers
4
+ describe CodeHelper do
5
+ let(:challenge) { Fabricate(:challenge, name: 'test', source_file: @source_file) }
6
+ let(:source) do
7
+ %q[
8
+ # This snippet should not be in the output.
9
+ puts "Random: #{rand}"
10
+
11
+ # Snippet: Hello, world!
12
+ puts 'Hello, world!'
13
+
14
+ # Nor should this snippet
15
+ puts 'Done'
16
+ ]
17
+ end
18
+ let(:expected_snippet) do
19
+ %q[
20
+ puts 'Hello, world!'
21
+ ]
22
+ end
23
+
24
+ around do | example |
25
+ with_files(source: source) do | files |
26
+ @source_file = files.first
27
+ example.run
28
+ end
29
+ end
30
+
31
+ describe '#snippet_after' do
32
+ it 'returns the code block after the match (string)' do
33
+ snippet = challenge.snippet_after 'Snippet: Hello, world!'
34
+ expect(snippet.strip).to eq(expected_snippet.strip)
35
+ end
36
+
37
+ it 'returns the code block after the match (regex)' do
38
+ snippet = challenge.snippet_after(/Snippet: .*/)
39
+ expect(snippet.strip).to eq(expected_snippet.strip)
40
+ end
41
+
42
+ it 'returns nothing if no match is found' do
43
+ snippet = challenge.snippet_after 'Nothing matches'
44
+ expect(snippet).to be_empty
45
+ end
46
+ end
47
+
48
+ describe '#snippet_between' do
49
+ # Yes, whitespace doesn't work very well w/ snippet_between
50
+ let(:expected_snippet) do
51
+ %q[
52
+ puts "Random: #{rand}"
53
+ # Snippet: Hello, world!
54
+ puts 'Hello, world!'
55
+ ]
56
+ end
57
+
58
+ it 'inserts all code blocks between the matching regexes' do
59
+ snippet = challenge.snippet_between 'This snippet should not be in the output', 'Nor should this snippet'
60
+ expect(snippet.strip).to eq(expected_snippet.strip)
61
+ end
62
+
63
+ it 'inserts nothing unless both matches are found' do
64
+ # Neither match
65
+ snippet = challenge.snippet_between 'foo', 'bar'
66
+ expect(snippet.strip).to be_empty
67
+
68
+ # First matches
69
+ snippet = challenge.snippet_between 'This snippet should not be in the output', 'foo'
70
+ expect(snippet.strip).to be_empty
71
+
72
+ # Last matches
73
+ snippet = challenge.snippet_between 'foo', 'Nor should this snippet'
74
+ expect(snippet.strip).to be_empty
75
+ end
76
+
77
+ end
78
+
79
+ describe '#code_block' do
80
+ it 'generates markdown code blocks by default' do
81
+ expected = "```ruby\n" + source + "\n```\n"
82
+ code_block = challenge.code_block(challenge.source, 'ruby')
83
+ expect(code_block).to eq(expected)
84
+ end
85
+
86
+ it 'generates rst for format :rst' do
87
+ indented_source = source.lines.map do|line|
88
+ " #{line}"
89
+ end.join("\n")
90
+ expected = ".. code-block:: ruby\n" + indented_source + "\n"
91
+ code_block = challenge.code_block(challenge.source, 'ruby', format: :rst)
92
+ expect(code_block).to eq(expected)
93
+ end
94
+ end
95
+
96
+ def generate_doc_for(template_file, source_file)
97
+ doc_gen = DocumentationGenerator.new(template_file, 'testing')
98
+ challenge = Fabricate(:challenge, name: 'test', source_file: source_file)
99
+ doc_gen.process(challenge)
100
+ end
101
+
102
+ def with_files(files)
103
+ tmpfiles = []
104
+ begin
105
+ files.each do |k, v|
106
+ file = Tempfile.new(k.to_s)
107
+ file.write(v)
108
+ file.close
109
+ tmpfiles << file
110
+ end
111
+ yield tmpfiles.map(&:path)
112
+ ensure
113
+ tmpfiles.each { |tmpfile| tmpfile.unlink }
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,35 +1,56 @@
1
1
  module Polytrix
2
2
  describe DocumentationGenerator do
3
- let(:search_path) { 'spec/fixtures/src-doc' }
3
+ let(:scenario_name) { 'Quine' }
4
+ # let(:search_path) { 'spec/fixtures/src-doc' }
4
5
  let(:bound_data) { double }
5
- subject(:generator) { DocumentationGenerator.new(search_path) }
6
6
 
7
- context 'when no documentation exists' do
8
- it 'does nothing if there is no documentation for the scenario' do
9
- expect(generator.process 'no_doc', bound_data).to be_nil
7
+ describe 'process' do
8
+ let(:generated_doc) { generator.process bound_data }
9
+
10
+ context 'when template is readable' do
11
+ subject(:generator) { DocumentationGenerator.new('spec/fixtures/src-doc/quine.md.erb', scenario_name) }
12
+
13
+ it 'processes the template' do
14
+ expect(generated_doc).to include 'Examples for Quine scenario:'
15
+ end
16
+ end
17
+
18
+ context 'when template is not readable' do
19
+ subject(:generator) { DocumentationGenerator.new('non_existant_file.md', scenario_name) }
20
+ it 'processes the template' do
21
+ expect(generated_doc).to be_nil
22
+ end
10
23
  end
11
24
  end
12
25
 
13
- context 'when documentation does exist' do
26
+ describe 'code2doc' do
27
+ subject(:generator) { DocumentationGenerator.new }
14
28
 
15
- let(:generated_doc) { generator.process 'Quine', bound_data }
29
+ let(:source_code) do
30
+ <<-eos.gsub(/^( |\t)+/, '')
31
+ #!/usr/bin/env ruby
16
32
 
17
- it 'returns the generated document as a string' do
18
- expect(generated_doc).to be_a(String)
33
+ # Comments are documentation
34
+ puts 'And this is a code block'
35
+ eos
19
36
  end
20
37
 
21
- context 'ERB processing' do
22
- it 'processes scenario' do
23
- expect(generated_doc).to include 'Examples for Quine scenario:'
24
- end
25
-
26
- it 'processes Polytrix.implementors' do
27
- fail 'This test requires implementors' unless Polytrix.implementors
38
+ let(:source_file) do
39
+ file = Tempfile.new(['source', '.rb'])
40
+ file.write source_code
41
+ file.close
42
+ file.path
43
+ end
28
44
 
29
- Polytrix.implementors.each do |implementor|
30
- expect(generated_doc).to include "## #{implementor}"
31
- end
32
- end
45
+ it 'converts source code to documentation' do
46
+ expect(generator.code2doc(source_file, 'ruby')).to eq(
47
+ <<-eos.gsub(/^( |\t)+/, '')
48
+ Comments are documentation
49
+ ```ruby
50
+ puts 'And this is a code block'
51
+ ```
52
+ eos
53
+ )
33
54
  end
34
55
  end
35
56
  end
@@ -1,8 +1,8 @@
1
1
  module Polytrix
2
2
  module Core
3
- describe FileFinder do
3
+ describe FileSystemHelper do
4
4
  subject(:finder) do
5
- Object.new.extend(Polytrix::Core::FileFinder)
5
+ Object.new.extend(Polytrix::Core::FileSystemHelper)
6
6
  end
7
7
 
8
8
  it 'finds files within the search path' do
@@ -12,10 +12,11 @@ module Polytrix
12
12
  end
13
13
 
14
14
  it 'raises FileNotFound except if a file is not found' do
15
- expect { finder.find_file 'spec/fixtures/src-doc', 'quinez' }.to raise_error FileFinder::FileNotFound
15
+ expect { finder.find_file 'spec/fixtures/src-doc', 'quinez' }.to raise_error FileSystemHelper::FileNotFound
16
16
  end
17
17
 
18
18
  private
19
+
19
20
  def path(p)
20
21
  Pathname.new p
21
22
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Polytrix
4
+ describe Implementor do
5
+ subject(:implementor) { described_class.new(name: 'test', language: 'ruby', basedir: 'sdks/test') }
6
+ let(:executor) { double('executor') }
7
+
8
+ before do
9
+ subject.executor = executor
10
+ end
11
+
12
+ describe '#bootstrap' do
13
+ it 'executes script/bootstrap' do
14
+ expect(executor).to receive(:execute).with('./scripts/bootstrap', cwd: Pathname.new(File.absolute_path('sdks/test')), prefix: 'test')
15
+ implementor.bootstrap
16
+ end
17
+ end
18
+
19
+ describe '#build_challenge' do
20
+ subject(:implementor) { Polytrix::Implementor.new name: 'some_sdk', basedir: File.absolute_path('spec/fixtures') }
21
+ let(:challenge) { Fabricate(:challenge, name: 'factorial', vars: {}) }
22
+
23
+ it 'builds a Challenge' do
24
+ expect(challenge).to be_an_instance_of Polytrix::Challenge
25
+ end
26
+
27
+ it 'finds the source' do
28
+ expected_file = Pathname.new 'spec/fixtures/factorial.py'
29
+ expect(challenge.source_file).to eq(expected_file)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,26 +1,44 @@
1
1
  module Polytrix
2
- module Core
3
- describe Manifest do
4
- describe '#from_yaml' do
5
- subject(:manifest) { described_class.from_yaml 'spec/fixtures/polytrix.yml' }
2
+ describe Manifest do
3
+ describe '#from_yaml' do
4
+ subject(:manifest) { described_class.from_yaml 'spec/fixtures/polytrix_tests.yml' }
6
5
 
7
- it 'initializes a manifest' do
8
- expect(manifest).to be_an_instance_of Polytrix::Manifest
9
- end
6
+ it 'initializes a manifest' do
7
+ expect(manifest).to be_an_instance_of Polytrix::Manifest
8
+ end
10
9
 
11
- it 'processes ERB' do
12
- expect(manifest.global_env['LOCALE']).to eq(ENV['LANG'])
13
- end
10
+ it 'processes ERB' do
11
+ expect(manifest.global_env['LOCALE']).to eq(ENV['LANG'])
12
+ end
13
+
14
+ it 'parses global_env' do
15
+ expect(manifest.global_env).to be_an_instance_of Polytrix::Manifest::Environment
16
+ end
14
17
 
15
- it 'parses global_env' do
16
- expect(manifest.global_env).to be_an_instance_of Polytrix::Manifest::Environment
18
+ it 'parses suites' do
19
+ expect(manifest.suites).to be_an_instance_of Polytrix::Manifest::Suites
20
+ end
21
+
22
+ describe '#find_suite' do
23
+ before(:each) do
24
+ Polytrix.configuration.test_manifest = 'samples/polytrix_tests.yml'
25
+ end
26
+ it 'returns nil if no suite matches' do
27
+ suite = subject.find_suite('none')
28
+ expect(suite).to be_nil
17
29
  end
18
30
 
19
- it 'parses suites' do
20
- expect(manifest.suites).to be_an_instance_of Polytrix::Manifest::Suites
31
+ it 'returns the suite if one is found' do
32
+ suite = subject.find_suite('Katas')
33
+ expect(suite).to be_an_instance_of Polytrix::Manifest::Suite
21
34
  end
22
35
 
36
+ it 'is not case sensitive' do
37
+ suite = subject.find_suite('katas')
38
+ expect(suite).to be_an_instance_of Polytrix::Manifest::Suite
39
+ end
23
40
  end
41
+
24
42
  end
25
43
  end
26
44
  end
@@ -19,7 +19,7 @@ module Polytrix
19
19
 
20
20
  before do
21
21
  allow(challenge_runner).to receive(:challenge_command).with(env[:env_file], Pathname.new('test.js')).and_return('some command to execute')
22
- allow(challenge_runner).to receive(:run_command).with('some command to execute').and_return Polytrix::Result.new(process: 'a', source: 'b', data: 'c')
22
+ allow(challenge_runner).to receive(:run_command).with('some command to execute').and_return Polytrix::Result.new(execution_result: 'a', source_file: 'b')
23
23
  allow(app).to receive(:call).with(env)
24
24
  end
25
25
 
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ module Polytrix
4
+ describe Result do
5
+ describe '#status' do
6
+ context 'mixed pass/fail' do
7
+ let(:subject) do
8
+ Polytrix::Result.new(
9
+ validations: [
10
+ { validated_by: 'max', result: 'passed' },
11
+ { validated_by: 'polytrix', result: 'failed' }
12
+ ]
13
+ ).status
14
+ end
15
+ it 'reports the failed status' do
16
+ is_expected.to eq('failed')
17
+ end
18
+ end
19
+ context 'mix passed/pending/skipped' do
20
+ let(:subject) do
21
+ Polytrix::Result.new(
22
+ validations: [
23
+ { validated_by: 'max', result: 'passed' },
24
+ { validated_by: 'polytrix', result: 'pending' },
25
+ { validated_by: 'john doe', result: 'skipped' }
26
+ ]
27
+ ).status
28
+ end
29
+ it 'reports the passed status' do
30
+ is_expected.to eq('passed')
31
+ end
32
+ end
33
+ context 'mix pending/skipped' do
34
+ let(:subject) do
35
+ Polytrix::Result.new(
36
+ validations: [
37
+ { validated_by: 'max', result: 'pending' },
38
+ { validated_by: 'polytrix', result: 'pending' },
39
+ { validated_by: 'john doe', result: 'skipped' }
40
+ ]
41
+ ).status
42
+ end
43
+ it 'reports the pending status' do
44
+ is_expected.to eq('pending')
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ module Polytrix
4
+ describe Validations do
5
+ describe '#coerce' do
6
+ it 'accepts an array when built via Result' do
7
+ Polytrix::Result.new(
8
+ validations: [
9
+ { validated_by: 'max', result: 'passed' },
10
+ { validated_by: 'polytrix', result: 'skipped' }
11
+ ]
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Polytrix
2
+ describe 'ValidatorRegistry' do
3
+ subject(:registry) { Polytrix::ValidatorRegistry }
4
+
5
+ describe '#register' do
6
+ it 'registers a validator' do
7
+ callback = proc do |challenge|
8
+ expect(challenge[:result].execution_result.exitstatus).to eq(0)
9
+ end
10
+
11
+ expect(registry.validators).to be_empty
12
+ registry.register suite: 'java', sample: 'hello world', &callback
13
+ validator = registry.validators.first
14
+ expect(validator.suite).to eql('java')
15
+ expect(validator.sample).to eql('hello world')
16
+ expect(validator.instance_variable_get('@callback')).to eql(callback)
17
+ end
18
+ end
19
+
20
+ describe '#validators_for' do
21
+ let(:java_hello_world_validator) { Fabricate(:validator, suite: 'java', sample: 'hello world') }
22
+ let(:java_validator) { Fabricate(:validator, suite: 'java', sample: //) }
23
+ let(:ruby_validator) { Fabricate(:validator, suite: 'ruby') }
24
+
25
+ before do
26
+ registry.register(java_hello_world_validator)
27
+ registry.register(java_validator)
28
+ registry.register(ruby_validator)
29
+ end
30
+
31
+ it 'returns registered validators that match the scope of the challenge' do
32
+ challenge = Fabricate(:challenge, suite: 'java', name: 'hello world')
33
+ validators = registry.validators_for challenge
34
+ expect(validators).to include(java_hello_world_validator, java_validator)
35
+ expect(validators).to_not include(ruby_validator)
36
+ end
37
+ end
38
+ end
39
+ end