soaspec 0.2.24 → 0.2.25

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 (83) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +15 -15
  3. data/.gitlab-ci.yml +51 -33
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +2 -2
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/ChangeLog +588 -577
  8. data/Gemfile +6 -6
  9. data/LICENSE.txt +21 -21
  10. data/README.md +230 -230
  11. data/Rakefile +50 -42
  12. data/Todo.md +15 -15
  13. data/exe/soaspec +137 -123
  14. data/exe/xml_to_yaml_file +42 -42
  15. data/lib/soaspec.rb +103 -101
  16. data/lib/soaspec/core_ext/hash.rb +42 -35
  17. data/lib/soaspec/cucumber/generic_steps.rb +85 -85
  18. data/lib/soaspec/demo.rb +4 -4
  19. data/lib/soaspec/exchange/exchange.rb +117 -111
  20. data/lib/soaspec/exchange/exchange_extractor.rb +83 -83
  21. data/lib/soaspec/exchange/exchange_properties.rb +26 -26
  22. data/lib/soaspec/exchange/exchange_repeater.rb +19 -19
  23. data/lib/soaspec/exchange/request_builder.rb +68 -68
  24. data/lib/soaspec/exchange/variable_storer.rb +22 -22
  25. data/lib/soaspec/exchange_handlers/exchange_handler.rb +130 -126
  26. data/lib/soaspec/exchange_handlers/handler_accessors.rb +130 -130
  27. data/lib/soaspec/exchange_handlers/request/rest_request.rb +49 -0
  28. data/lib/soaspec/exchange_handlers/request/soap_request.rb +39 -0
  29. data/lib/soaspec/exchange_handlers/response_extractor.rb +82 -82
  30. data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +109 -109
  31. data/lib/soaspec/exchange_handlers/rest_handler.rb +287 -259
  32. data/lib/soaspec/exchange_handlers/rest_methods.rb +63 -44
  33. data/lib/soaspec/exchange_handlers/rest_parameters.rb +90 -86
  34. data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +40 -21
  35. data/lib/soaspec/exchange_handlers/soap_handler.rb +239 -235
  36. data/lib/soaspec/exe_helpers.rb +92 -92
  37. data/lib/soaspec/generate_server.rb +46 -37
  38. data/lib/soaspec/generator/.rspec.erb +5 -5
  39. data/lib/soaspec/generator/.travis.yml.erb +5 -5
  40. data/lib/soaspec/generator/Gemfile.erb +8 -8
  41. data/lib/soaspec/generator/README.md.erb +29 -29
  42. data/lib/soaspec/generator/Rakefile.erb +19 -19
  43. data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
  44. data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
  45. data/lib/soaspec/generator/features/support/env.rb.erb +3 -0
  46. data/lib/soaspec/generator/generate_exchange.html.erb +47 -35
  47. data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
  48. data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
  49. data/lib/soaspec/generator/lib/new_rest_service.rb.erb +56 -51
  50. data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
  51. data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
  52. data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
  53. data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
  54. data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
  55. data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
  56. data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
  57. data/lib/soaspec/generator/template/soap_template.xml +6 -6
  58. data/lib/soaspec/indifferent_hash.rb +7 -7
  59. data/lib/soaspec/interpreter.rb +39 -39
  60. data/lib/soaspec/matchers.rb +114 -114
  61. data/lib/soaspec/not_found_errors.rb +13 -13
  62. data/lib/soaspec/o_auth2.rb +128 -128
  63. data/lib/soaspec/soaspec_shared_examples.rb +24 -24
  64. data/lib/soaspec/spec_logger.rb +122 -121
  65. data/lib/soaspec/template_reader.rb +28 -28
  66. data/lib/soaspec/test_server/bank.wsdl +90 -90
  67. data/lib/soaspec/test_server/get_bank.rb +164 -164
  68. data/lib/soaspec/test_server/id_manager.rb +39 -39
  69. data/lib/soaspec/test_server/invoices.rb +27 -27
  70. data/lib/soaspec/test_server/namespace.xml +14 -14
  71. data/lib/soaspec/test_server/note.xml +5 -5
  72. data/lib/soaspec/test_server/puppy_service.rb +19 -19
  73. data/lib/soaspec/test_server/test_attribute.rb +12 -12
  74. data/lib/soaspec/test_server/test_namespace.rb +12 -12
  75. data/lib/soaspec/version.rb +4 -4
  76. data/lib/soaspec/virtual_server.rb +174 -174
  77. data/lib/soaspec/wait.rb +41 -41
  78. data/lib/soaspec/wsdl_generator.rb +215 -215
  79. data/soaspec.gemspec +56 -53
  80. data/test.wsdl +116 -116
  81. data/test.xml +10 -10
  82. data/test_wsdl.rb +41 -41
  83. metadata +38 -6
data/Rakefile CHANGED
@@ -1,42 +1,50 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- require 'rake/clean'
4
- require 'yard'
5
-
6
- ENV['folder'] ||= ''
7
- ENV['test'] ||= ''
8
-
9
- desc 'Run tests'
10
- RSpec::Core::RakeTask.new(spec: %i[clean clobber start_test_server]) do |t|
11
- t.pattern = "spec/**/#{ENV['folder']}*/#{ENV['test']}*_spec.rb"
12
- end
13
-
14
- task :parallel => [:clean, :clobber, :start_test_server] do
15
- puts `parallel_rspec spec`
16
- end
17
-
18
- task default: :spec
19
-
20
- CLEAN.include 'tmp/*'
21
- CLOBBER.include 'logs/*'
22
-
23
- desc 'Start virtual web service'
24
- task :start_test_server do
25
- ENV['leave_server_running'] = 'true' # This will stop created suites from killing this service
26
- mkdir_p 'logs'
27
- ENV['test_server_pid'] = Process.spawn('ruby', 'exe/soaspec', 'virtual_server', err: %w[logs/test_server.log w]).to_s
28
- sleep 2 # Wait a little for virtual server to start up
29
- puts 'Running test server at pid ' + ENV['test_server_pid']
30
- end
31
-
32
- YARD::Rake::YardocTask.new do |t|
33
- t.files = %w[features/**/*.feature features/**/*.rb lib/soaspec/cucumber/*.rb] # lib/soaspec/cucumber/*.rb]
34
- end
35
-
36
- desc 'Ensure system has all docs'
37
- task :must_have_docs do
38
- yard = `yard`
39
- puts yard
40
- percentage = yard.lines.last.strip.split('%').first.to_f
41
- raise 'Must be fully documented' unless percentage == 100.00
42
- end
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/clean'
4
+ require 'yard'
5
+ require 'yard/doctest/rake'
6
+
7
+ ENV['folder'] ||= ''
8
+ ENV['test'] ||= ''
9
+
10
+ desc 'Run tests'
11
+ RSpec::Core::RakeTask.new(spec: %i[clean clobber start_test_server]) do |t|
12
+ t.pattern = "spec/**/#{ENV['folder']}*/#{ENV['test']}*_spec.rb"
13
+ end
14
+
15
+ task :parallel => [:clean, :clobber, :start_test_server] do
16
+ puts `parallel_rspec spec`
17
+ end
18
+
19
+ task default: :spec
20
+
21
+ CLEAN.include 'tmp/*'
22
+ CLOBBER.include 'logs/*'
23
+
24
+ desc 'Start virtual web service'
25
+ task :start_test_server do
26
+ ENV['leave_server_running'] = 'true' # This will stop created suites from killing this service
27
+ mkdir_p 'logs'
28
+ ENV['test_server_pid'] = Process.spawn('ruby', 'exe/soaspec', 'virtual_server', err: %w[logs/test_server.log w]).to_s
29
+ sleep 2 # Wait a little for virtual server to start up
30
+ puts 'Running test server at pid ' + ENV['test_server_pid']
31
+ end
32
+
33
+ YARD::Rake::YardocTask.new do |t|
34
+ t.files = %w[features/**/*.feature features/**/*.rb lib/soaspec/cucumber/*.rb] # lib/soaspec/cucumber/*.rb]
35
+ end
36
+
37
+ desc 'Ensure system has all docs'
38
+ task :must_have_docs do
39
+ yard = `yard`
40
+ puts yard
41
+ percentage = yard.lines.last.strip.split('%').first.to_f
42
+ raise 'Must be fully documented' unless percentage == 100.00
43
+ end
44
+
45
+ desc 'Test examples shown in documentation'
46
+ YARD::Doctest::RakeTask.new do |task|
47
+ task.doctest_opts = %w[-v]
48
+ # task.pattern = 'lib/**/*.rb'
49
+ task.pattern = 'lib/soaspec/core_ext/hash.rb'
50
+ end
data/Todo.md CHANGED
@@ -1,15 +1,15 @@
1
- * `yard` should show everything documented
2
- * Rubocop should have 0 offenses
3
- * Unit tests
4
- * OAuth class, etc
5
- * Get initial `soaspec new` working with TODOs as placeholders for how to get started
6
- * Request method from within exchange
7
- * Use this in tests
8
- * Basic service generator
9
- * Give examples and convenience methods for building classes for each SOAP or REST operation
10
- * Potentially have in built use of 'vcr' and 'http_stub' gems
11
- * Handle proxies to record traffic for MiddleWare testing
12
- * soaspec generate
13
- * Get wsdl generator working for non complex gems (Put on hold til new Savon version)
14
- * Generate from a RAML
15
- * Much more - please raise an issue for suggestion
1
+ * `yard` should show everything documented
2
+ * Rubocop should have 0 offenses
3
+ * Unit tests
4
+ * OAuth class, etc
5
+ * Get initial `soaspec new` working with TODOs as placeholders for how to get started
6
+ * Request method from within exchange
7
+ * Use this in tests
8
+ * Basic service generator
9
+ * Give examples and convenience methods for building classes for each SOAP or REST operation
10
+ * Potentially have in built use of 'vcr' and 'http_stub' gems
11
+ * Handle proxies to record traffic for MiddleWare testing
12
+ * soaspec generate
13
+ * Get wsdl generator working for non complex gems (Put on hold til new Savon version)
14
+ * Generate from a RAML
15
+ * Much more - please raise an issue for suggestion
data/exe/soaspec CHANGED
@@ -1,123 +1,137 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'thor'
4
- $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
- require 'savon'
6
- require 'soaspec'
7
- require 'soaspec/virtual_server'
8
- require 'soaspec/wsdl_generator'
9
-
10
- module Soaspec
11
- # Common executable for Soaspec
12
- class Exe < Thor
13
- include Soaspec::ExeHelpers
14
- include Soaspec::WsdlGenerator
15
-
16
- long_desc <<-LONGDESC
17
- `soaspec new` will generate the initial files and folders for starting a testing project using soaspec
18
- \x5
19
-
20
- `soaspec new soap` will create example files testing against a SOAP service
21
- \x5
22
-
23
- `soaspec new rest` will create example files testing against a REST service
24
- LONGDESC
25
- desc 'new [type]', 'Initialize soaspec repository'
26
- option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
27
- option :virtual, type: :boolean, default: true, banner: 'Whether to set things up for a virtual server'
28
- def new(type = 'initial')
29
- @virtual = options[:virtual]
30
- @type = type
31
- puts "Creating files for soaspec. options are #{options}"
32
- create_file(filename: 'Gemfile')
33
- create_file(filename: 'Rakefile')
34
- create_file(filename: '.rspec')
35
- create_file(filename: 'README.md')
36
- create_file(filename: '.travis.yml') if options[:ci] == 'travis'
37
- create_folder 'lib'
38
- create_files_for type
39
- create_file(filename: 'config/data/default.yml') # Example of data file
40
- create_file(filename: 'spec/spec_helper.rb')
41
- puts "Run 'bundle install' to install necessary gems"
42
- puts "Run 'rake spec' to run the tests"
43
- end
44
-
45
- long_desc <<-LONGDESC
46
- `soaspec add rest` will generate the initial files and folders for starting a testing project using soaspec
47
- \x5
48
-
49
- `soaspec add soap` will create example files testing against a virtual SOAP service
50
- \x5
51
-
52
- LONGDESC
53
- desc 'add [type] [name]', 'Add new ExchangeHandler'
54
- def add(type = 'rest', name = 'TestService')
55
- raise "Type '#{type}' is not available" unless %w[rest soap].include? type
56
-
57
- @name = name # Use instance variable for ERB
58
- create_file filename: File.join('lib', "#{name.snakecase}.rb"),
59
- content: retrieve_contents(File.join('lib', "new_#{type}_service.rb"))
60
- end
61
-
62
- desc 'cucumber', 'Add cucumber generic steps template within step_definitions folder'
63
- def cucumber
64
- create_file filename: File.join('features', 'step_definitions', 'generic_steps.rb'),
65
- content: retrieve_contents(File.join('../cucumber', 'generic_steps.rb'), false)
66
- end
67
-
68
- desc 'generate', 'Generate initial test code from wsdl'
69
- long_desc <<-LONGDESC
70
- If no wsdl is given a server will be started from which code to generate Exchanges
71
-
72
- `soaspec generate wsdl=wsdl name=ServiceName ` will generate the initial files and folders to test each operation in a wsdl
73
- \x5
74
- Additionally the auth parameter can be used to use basic authentication to retrieve the WSDL.
75
- To do use the following `soaspec generate --auth=basic`
76
- Note: This is still a work in progress and will only work for a very simple wsdl
77
- LONGDESC
78
- option :wsdl, default: nil, aliases: :w
79
- option :name, default: 'Service', aliases: :n
80
- option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
81
- option :auth
82
- option :open_browser, default: 'true'
83
- option :string_default, default: 'test string'
84
- def generate
85
- if options[:wsdl]
86
- generate_from_wsdl(options)
87
- else
88
- require 'launchy'
89
- require 'soaspec/generate_server'
90
- Soaspec::GenerateServer.run! do
91
- Launchy.open 'http://localhost:8999' if options[:open_browser] == 'true'
92
- end
93
- end
94
- end
95
-
96
- long_desc <<-LONGDESC
97
- Run virtual web services on localhost. See root for documentation of web services provided.
98
- LONGDESC
99
- desc 'virtual_server [port]', 'Run virtual web service on localhost'
100
- def virtual_server(port = '4999')
101
- ENV['port'] = port
102
- require 'soaspec/virtual_server'
103
- Soaspec::VirtualServer.run!(Port: port)
104
- end
105
-
106
- long_desc <<-LONGDESC
107
- Run pry with Soaspec and other relevant libraries loaded. Pass either the relative path to files desired with a
108
- '.rb' extension or the path to the folder to be loaded with 'require_all'
109
- LONGDESC
110
- desc 'pry [required_files]', 'Run pry with Soaspec and other relevant libraries loaded'
111
- def pry(required_files = nil)
112
- require 'soaspec'
113
-
114
- require 'require_all'
115
- require_all required_files if required_files
116
-
117
- require 'pry'
118
- Pry.start
119
- end
120
- end
121
- end
122
-
123
- Soaspec::Exe.start(ARGV)
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'savon'
6
+ require 'soaspec'
7
+ require 'soaspec/virtual_server'
8
+ require 'soaspec/wsdl_generator'
9
+
10
+ module Soaspec
11
+ # Common executable for Soaspec
12
+ class Exe < Thor
13
+ include Soaspec::ExeHelpers
14
+ include Soaspec::WsdlGenerator
15
+
16
+ long_desc <<-LONGDESC
17
+ `soaspec new` will generate the initial files and folders for starting a testing project using soaspec
18
+ \x5
19
+
20
+ `soaspec new soap` will create example files testing against a SOAP service
21
+ \x5
22
+
23
+ `soaspec new rest` will create example files testing against a REST service
24
+ LONGDESC
25
+ desc 'new [type]', 'Initialize soaspec repository'
26
+ option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
27
+ option :virtual, type: :boolean, default: true, banner: 'Whether to set things up for a virtual server'
28
+ def new(type = 'initial')
29
+ @virtual = options[:virtual]
30
+ @type = type
31
+ puts "Creating files for soaspec. options are #{options}"
32
+ create_file(filename: 'Gemfile')
33
+ create_file(filename: 'Rakefile')
34
+ create_file(filename: '.rspec')
35
+ create_file(filename: 'README.md')
36
+ create_file(filename: '.travis.yml') if options[:ci] == 'travis'
37
+ create_folder 'lib'
38
+ create_files_for type
39
+ create_file(filename: 'config/data/default.yml') # Example of data file
40
+ create_file(filename: 'spec/spec_helper.rb')
41
+ puts "Run 'bundle install' to install necessary gems"
42
+ puts "Run 'rake spec' to run the tests"
43
+ end
44
+
45
+ long_desc <<-LONGDESC
46
+ `soaspec add rest` will generate the initial files and folders for starting a testing project using soaspec
47
+ \x5
48
+
49
+ `soaspec add soap` will create example files testing against a virtual SOAP service
50
+ \x5
51
+
52
+ LONGDESC
53
+ desc 'add [type] [name]', 'Add new ExchangeHandler'
54
+ def add(type = 'rest', name = 'TestService')
55
+ raise "Type '#{type}' is not available" unless %w[rest soap].include? type
56
+
57
+ @name = name # Use instance variable for ERB
58
+ create_file filename: File.join('lib', "#{name.snakecase}.rb"),
59
+ content: retrieve_contents(File.join('lib', "new_#{type}_service.rb"))
60
+ end
61
+
62
+ long_desc <<-LONGDESC
63
+ `soaspec cucumber` will add generic steps file within step definitions folder. It will also
64
+ add Gemfile, and other Cucumber setup files if not already added
65
+ \x5
66
+
67
+ LONGDESC
68
+ desc 'cucumber', 'Add cucumber generic steps template within step_definitions folder'
69
+ def cucumber
70
+ @cucumber = true
71
+ create_file(filename: 'Gemfile', ignore_if_present: true)
72
+ create_file(filename: 'features/support/env.rb', ignore_if_present: true)
73
+ create_file filename: File.join('features', 'step_definitions', 'generic_steps.rb'),
74
+ content: retrieve_contents(File.join('../cucumber', 'generic_steps.rb'), false)
75
+ end
76
+
77
+ desc 'generate', 'Generate initial test code from wsdl'
78
+ long_desc <<-LONGDESC
79
+ If no wsdl is given a server will be started from which code to generate Exchanges
80
+
81
+ `soaspec generate wsdl=wsdl name=ServiceName ` will generate the initial files and folders to test each operation in a wsdl
82
+ \x5
83
+ Additionally the auth parameter can be used to use basic authentication to retrieve the WSDL.
84
+ To do use the following `soaspec generate --auth=basic`
85
+ Note: This is still a work in progress and will only work for a very simple wsdl
86
+ LONGDESC
87
+ option :wsdl, default: nil, aliases: :w
88
+ option :name, default: 'Service', aliases: :n
89
+ option :ci, default: 'jenkins', banner: 'What Continuous Integration is used'
90
+ option :auth
91
+ option :open_browser, default: 'true'
92
+ option :string_default, default: 'test string'
93
+ option :port, default: nil, banner: 'What port to run generate server. Default is random'
94
+ def generate
95
+ if options[:wsdl]
96
+ generate_from_wsdl(options)
97
+ else
98
+ require 'launchy'
99
+ require 'soaspec/generate_server'
100
+ require 'random-port'
101
+ port = options[:port] || RandomPort::Pool.new.acquire.to_s
102
+ puts "Using random port '#{port}' for hosting generate server"
103
+
104
+ Soaspec::GenerateServer.run!(port: port) do
105
+ Launchy.open "http://localhost:#{port}" if options[:open_browser] == 'true'
106
+ end
107
+ end
108
+ end
109
+
110
+ long_desc <<-LONGDESC
111
+ Run virtual web services on localhost. See root for documentation of web services provided.
112
+ LONGDESC
113
+ desc 'virtual_server [port]', 'Run virtual web service on localhost'
114
+ def virtual_server(port = '4999')
115
+ ENV['port'] = port
116
+ require 'soaspec/virtual_server'
117
+ Soaspec::VirtualServer.run!(port: port)
118
+ end
119
+
120
+ long_desc <<-LONGDESC
121
+ Run pry with Soaspec and other relevant libraries loaded. Pass either the relative path to files desired with a
122
+ '.rb' extension or the path to the folder to be loaded with 'require_all'
123
+ LONGDESC
124
+ desc 'pry [required_files]', 'Run pry with Soaspec and other relevant libraries loaded'
125
+ def pry(required_files = nil)
126
+ require 'soaspec'
127
+
128
+ require 'require_all'
129
+ require_all required_files if required_files
130
+
131
+ require 'pry'
132
+ Pry.start
133
+ end
134
+ end
135
+ end
136
+
137
+ Soaspec::Exe.start(ARGV)
data/exe/xml_to_yaml_file CHANGED
@@ -1,42 +1,42 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'xmlsimple'
4
- require 'yaml'
5
- require 'fileutils'
6
-
7
- $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
-
9
- require 'soaspec'
10
-
11
- include Soaspec::ExeHelpers
12
-
13
- default_output_file = 'output.yml'
14
-
15
- # For all keys in a Hash, convert Camelcase to underscore separated
16
- def convert_hash_keys(value)
17
- case value
18
- when Array
19
- value.map { |v| convert_hash_keys(v) }
20
- when Hash
21
- Hash[value.map { |k, v| [k.snakecase, convert_hash_keys(v)] }]
22
- else
23
- value
24
- end
25
- end
26
-
27
- # Remove arrays created as another string
28
- def clean_up_yaml(yaml_string)
29
- yaml_string = yaml_string.gsub(/\R+(\s*)-/, '').gsub(/{}/, "''") # Remove arrays, {} -> ''
30
- # Insert new line where there are 2 ':' on 1 line. Issue from first gsub
31
- yaml_string.gsub(/:(\s)(\w*):/) { |s| s.insert(1, "\n") }
32
- end
33
-
34
- if ARGV[0]
35
- warn "Using '#{default_output_file}' as default output file since no 2nd argument passed" unless ARGV[1]
36
- hash = XmlSimple.xml_in(ARGV[0])
37
- converted = convert_hash_keys hash
38
- yaml_file = clean_up_yaml(converted.to_yaml)
39
- create_file(filename: ARGV[1] || default_output_file, content: yaml_file)
40
- else
41
- puts 'usage: xml_to_yaml_file [input.xml] [output.yml] '
42
- end
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'xmlsimple'
4
+ require 'yaml'
5
+ require 'fileutils'
6
+
7
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
+
9
+ require 'soaspec'
10
+
11
+ include Soaspec::ExeHelpers
12
+
13
+ default_output_file = 'output.yml'
14
+
15
+ # For all keys in a Hash, convert Camelcase to underscore separated
16
+ def convert_hash_keys(value)
17
+ case value
18
+ when Array
19
+ value.map { |v| convert_hash_keys(v) }
20
+ when Hash
21
+ Hash[value.map { |k, v| [k.snakecase, convert_hash_keys(v)] }]
22
+ else
23
+ value
24
+ end
25
+ end
26
+
27
+ # Remove arrays created as another string
28
+ def clean_up_yaml(yaml_string)
29
+ yaml_string = yaml_string.gsub(/\R+(\s*)-/, '').gsub(/{}/, "''") # Remove arrays, {} -> ''
30
+ # Insert new line where there are 2 ':' on 1 line. Issue from first gsub
31
+ yaml_string.gsub(/:(\s)(\w*):/) { |s| s.insert(1, "\n") }
32
+ end
33
+
34
+ if ARGV[0]
35
+ warn "Using '#{default_output_file}' as default output file since no 2nd argument passed" unless ARGV[1]
36
+ hash = XmlSimple.xml_in(ARGV[0])
37
+ converted = convert_hash_keys hash
38
+ yaml_file = clean_up_yaml(converted.to_yaml)
39
+ create_file(filename: ARGV[1] || default_output_file, content: yaml_file)
40
+ else
41
+ puts 'usage: xml_to_yaml_file [input.xml] [output.yml] '
42
+ end