polytrix 0.0.1 → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
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