ams_layout 0.0.2

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.pryrc +8 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +12 -0
  7. data/Gemfile.lock +134 -0
  8. data/Guardfile +11 -0
  9. data/LICENSE +22 -0
  10. data/README.md +42 -0
  11. data/Rakefile +116 -0
  12. data/ams_layout.gemspec +32 -0
  13. data/bin/ams_layout +10 -0
  14. data/lib/ams_layout/browser_loader.rb +99 -0
  15. data/lib/ams_layout/cli/config.rb +250 -0
  16. data/lib/ams_layout/cli/generate.rb +145 -0
  17. data/lib/ams_layout/cli.rb +29 -0
  18. data/lib/ams_layout/client.rb +190 -0
  19. data/lib/ams_layout/core_ext/string.rb +30 -0
  20. data/lib/ams_layout/core_ext.rb +11 -0
  21. data/lib/ams_layout/delegate_writer.rb +348 -0
  22. data/lib/ams_layout/pages/login_page.rb +69 -0
  23. data/lib/ams_layout/pages/prequal_detail.rb +26 -0
  24. data/lib/ams_layout/pages.rb +36 -0
  25. data/lib/ams_layout/parser.rb +137 -0
  26. data/lib/ams_layout/version.rb +3 -0
  27. data/lib/ams_layout/writer.rb +124 -0
  28. data/lib/ams_layout.rb +198 -0
  29. data/spec/data/layout-small.yml +25 -0
  30. data/spec/data/layout-small.yml.aliases +22 -0
  31. data/spec/data/layout.yml +652 -0
  32. data/spec/data/layout.yml.aliases +613 -0
  33. data/spec/lib/ams_layout/ams_layout_spec.rb +7 -0
  34. data/spec/lib/ams_layout/cli/config_spec.rb +471 -0
  35. data/spec/lib/ams_layout/cli/generate_spec.rb +188 -0
  36. data/spec/lib/ams_layout/cli_spec.rb +35 -0
  37. data/spec/lib/ams_layout/client_spec.rb +93 -0
  38. data/spec/lib/ams_layout/delegate_writer_spec.rb +80 -0
  39. data/spec/lib/ams_layout/writer_spec.rb +64 -0
  40. data/spec/spec_helper.rb +7 -0
  41. data/spec/spec_helper_spec.rb +27 -0
  42. data/spec/support/asserts.rb +13 -0
  43. data/spec/support/dirs.rb +45 -0
  44. data/spec/support/helpers.rb +46 -0
  45. metadata +231 -0
@@ -0,0 +1,250 @@
1
+ ##############################################################################
2
+ # File:: config.rb
3
+ # Purpose:: Config command
4
+ #
5
+ # Author:: Jeff McAffee 2014-07-08
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+ module AmsLayout
11
+
12
+ class Config < Thor
13
+
14
+ class Add < Thor
15
+
16
+ desc "env <envname> <url>", "add a environment url"
17
+ def env(envname, url)
18
+ with_loaded_config do
19
+ unless AmsLayout.configuration.base_urls.key? envname.to_sym
20
+ AmsLayout.configuration.base_urls[envname.to_sym] = url
21
+ else
22
+ say "environment '#{envname}' already exists", :red
23
+ end
24
+ end
25
+ end
26
+
27
+ desc "credentials <envname> <username> <pass>", "add login credentials for an environment"
28
+ def credentials(envname, username, pass)
29
+ with_loaded_config do
30
+ if AmsLayout.configuration.base_urls.key? envname.to_sym
31
+ unless AmsLayout.configuration.credentials.key? envname.to_sym
32
+ AmsLayout.configuration.credentials[envname.to_sym] = [username, pass]
33
+ else
34
+ say "credentials already exist for environment '#{envname}'"
35
+ end
36
+ else
37
+ say "environment '#{envname}' doesn't exist", :red
38
+ say "create environment before adding credentials", :red
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def with_loaded_config &block
46
+ fail "expecting block" unless block_given?
47
+
48
+ unless AmsLayout.load_configuration
49
+ say "Configuration file not found!", :red
50
+ say "Have you tried 'config init' first?"
51
+ return
52
+ end
53
+
54
+ yield
55
+
56
+ AmsLayout.save_configuration
57
+ end
58
+ end
59
+
60
+ desc "add [CATEGORY]", "add a configuration value"
61
+ subcommand "add", Add
62
+
63
+
64
+ class Show < Thor
65
+
66
+ desc "envs", "display configured environments"
67
+ def envs
68
+ with_loaded_config do
69
+ say "Environments:"
70
+
71
+ output = []
72
+ AmsLayout.configuration.base_urls.each do |env, url|
73
+ output << [env, url]
74
+ end
75
+ print_table output, indent: 8
76
+ end
77
+ end
78
+
79
+ desc "credentials <envname>", "display configured credentials for an environment"
80
+ long_desc <<-LD
81
+ Display configured credentials for an environment.
82
+
83
+ If an environment name is not provided, credentials for all
84
+ environments will be displayed.
85
+ LD
86
+ def credentials(envname=nil)
87
+ with_loaded_config do
88
+ say "credentials:"
89
+
90
+ output = []
91
+ AmsLayout.configuration.credentials.each do |env, cred|
92
+ if envname.nil? || env == envname.to_sym
93
+ output << [env, cred.first, cred.last]
94
+ end
95
+ end
96
+ print_table output, indent: 8
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def with_loaded_config &block
103
+ fail "expecting block" unless block_given?
104
+
105
+ unless AmsLayout.load_configuration
106
+ say "Configuration file not found!", :red
107
+ say "Have you tried 'config init' first?"
108
+ return
109
+ end
110
+
111
+ yield
112
+ end
113
+ end
114
+
115
+ desc "show [CATEGORY]", "display configuration values for [CATEGORY]"
116
+ subcommand "show", Show
117
+
118
+
119
+ class Del < Thor
120
+
121
+ desc "env <envname>", "delete an environment configuration"
122
+ def env(envname)
123
+ with_loaded_config do
124
+ if AmsLayout.configuration.base_urls.key?(envname.to_sym)
125
+ AmsLayout.configuration.base_urls.delete(envname.to_sym)
126
+ end
127
+ end
128
+
129
+ credentials(envname)
130
+ end
131
+
132
+ desc "credentials <envname>", "delete credentials for an environment"
133
+ def credentials(envname)
134
+ with_loaded_config do
135
+ if AmsLayout.configuration.credentials.key?(envname.to_sym)
136
+ AmsLayout.configuration.credentials.delete(envname.to_sym)
137
+ end
138
+ end
139
+ end
140
+
141
+ private
142
+
143
+ def with_loaded_config &block
144
+ fail "expecting block" unless block_given?
145
+
146
+ unless AmsLayout.load_configuration
147
+ say "Configuration file not found!", :red
148
+ say "Have you tried 'config init' first?"
149
+ return
150
+ end
151
+
152
+ yield
153
+
154
+ AmsLayout.save_configuration
155
+ end
156
+ end
157
+
158
+ desc "del [CATEGORY]", "delete a configuration value for [CATEGORY]"
159
+ subcommand "del", Del
160
+
161
+
162
+ desc "init <filedir>", "initialize a configuration file"
163
+ long_desc <<-LD
164
+ Create a configuration file.
165
+
166
+ If <filedir> is provided, config file will be written to the
167
+ given directory.
168
+
169
+ If <filedir> is not given, the configuration file will be
170
+ written to the current working directory.
171
+ LD
172
+ option :quiet, :type => :boolean, :default => false, :aliases => :q
173
+ def init(filedir = nil)
174
+ if filedir.nil?
175
+ filedir = Pathname.pwd + AmsLayout::CONFIG_FILE_NAME
176
+ else
177
+ filedir = Pathname(filedir) + AmsLayout::CONFIG_FILE_NAME unless filedir.to_s.end_with?("/#{AmsLayout::CONFIG_FILE_NAME}")
178
+ end
179
+
180
+ outpath = AmsLayout.save_configuration filedir
181
+ say("configuration written to #{outpath.to_s}", :green) unless options[:quiet]
182
+ end
183
+
184
+
185
+ desc "timeout <seconds>", "show or set the browser timeout period"
186
+ long_desc <<-LD
187
+ Show or set the browser timeout period.
188
+ Default value is 360.
189
+
190
+ If <seconds> is not provided, display the current setting.
191
+
192
+ <seconds> must be an integer value.
193
+ LD
194
+ def timeout(seconds=nil)
195
+ if seconds.nil?
196
+ with_loaded_config do
197
+ say "browser timeout: #{AmsLayout.configuration.browser_timeout}"
198
+ end
199
+ else
200
+ with_loaded_config(true) do
201
+ AmsLayout.configuration.browser_timeout = Integer(seconds)
202
+ end
203
+ end
204
+ rescue ArgumentError => e
205
+ say 'argument error: seconds must be an integer'
206
+ end
207
+
208
+
209
+ desc "defenv <envname>", "show or set the default environment"
210
+ long_desc <<-LD
211
+ Show or set the default environment.
212
+
213
+ If <envname> is not provided, display the current setting.
214
+
215
+ <envname> must be an existing environment.
216
+ LD
217
+ def defenv(envname=nil)
218
+ if envname.nil?
219
+ with_loaded_config do
220
+ say "default environment: #{AmsLayout.configuration.default_environment}"
221
+ end
222
+ return
223
+ end
224
+
225
+ with_loaded_config(true) do
226
+ if AmsLayout.configuration.base_urls.key? envname.to_sym
227
+ AmsLayout.configuration.default_environment = envname.to_sym
228
+ else
229
+ say "argument error: environment '#{envname}' has not been configured"
230
+ end
231
+ end
232
+ end
233
+
234
+ private
235
+
236
+ def with_loaded_config save = false
237
+ fail "expecting block" unless block_given?
238
+
239
+ unless AmsLayout.load_configuration
240
+ say "Configuration file not found!", :red
241
+ say "Have you tried 'config init' first?"
242
+ return
243
+ end
244
+
245
+ yield
246
+
247
+ AmsLayout.save_configuration if save
248
+ end
249
+ end # Config
250
+ end # AmsLayout
@@ -0,0 +1,145 @@
1
+ ##############################################################################
2
+ # File:: generate.rb
3
+ # Purpose:: Generate command
4
+ #
5
+ # Author:: Jeff McAffee 06/21/2014
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+ require 'thor'
11
+ require 'ams_layout/client'
12
+
13
+ module AmsLayout
14
+ class Generate < Thor
15
+
16
+ desc "layout [PATH]", "write layout data to a file"
17
+ long_desc <<-LD
18
+ Generate layout data file.
19
+
20
+ File will be named layout.yml and placed in the directory (PATH)
21
+ you specify.
22
+
23
+ Directory must already exist or an error will be thrown.
24
+ LD
25
+ option :env, :banner => "dev", :aliases => :e
26
+ def layout(path)
27
+ env = AmsLayout.configuration.default_environment
28
+ env = options[:env] if options[:env]
29
+ user, pass = credentials env
30
+
31
+ client.login(user, pass)
32
+ client.write_layout path, false
33
+ client.logout
34
+ end
35
+
36
+ desc "cls <opts> [PATH] [LAYOUT_PATH]", "write layout class to a file"
37
+ long_desc <<-LD
38
+ Generate layout class.
39
+
40
+ Options:
41
+
42
+ -n ClassName specify name of layout class (default: LoanEntryFields)
43
+
44
+ Arguments:
45
+
46
+ [PATH] Path to directory where layout class will be created.
47
+
48
+ [LAYOUT_PATH] Path to directory containing layout data (layout.yml)
49
+
50
+ Directories must already exist or an error will be thrown.
51
+ LD
52
+ option :name, :banner => "ClassName", :aliases => :n
53
+ def cls(path, layout_path)
54
+ if options[:name]
55
+ client.layout_class_name = options[:name]
56
+ end
57
+
58
+ client.write_layout_class path, layout_path
59
+ end
60
+
61
+ desc "delegate <opts> [PATH] [LAYOUT_PATH]", "write delegate class to a file"
62
+ long_desc <<-LD
63
+ Generate delegate class.
64
+
65
+ Options:
66
+
67
+ -d ClassName specify name of delegate class (default: DelegateLoanEntryFields)
68
+
69
+ Arguments:
70
+
71
+ [PATH] Path to directory where delegate class will be created.
72
+
73
+ [LAYOUT_PATH] Path to directory containing layout data (layout.yml)
74
+
75
+ Directories must already exist or an error will be thrown.
76
+ LD
77
+ option :delegate, :banner => "DelegateClassName", :aliases => :d
78
+ def delegate(path, layout_path)
79
+ if options[:delegate]
80
+ client.delegate_class_name = options[:delegate]
81
+ end
82
+
83
+ client.write_delegate_class path, layout_path
84
+ end
85
+
86
+ desc "all <opts> [PATH]", "write layout data, layout class, and delegate class files to a path"
87
+ long_desc <<-LD
88
+ Generate layout data file (layout.yml), layout class, and delegate layout class.
89
+
90
+ Options:
91
+
92
+ -n ClassName specify name of layout class (default: LoanEntryFields)
93
+
94
+ -d ClassName specify name of delegate class (default: DelegateLoanEntryFields)
95
+
96
+ Arguments:
97
+
98
+ [PATH] Path to directory where files will be created.
99
+
100
+ Directory must already exist or an error will be thrown.
101
+ LD
102
+ option :name, :banner => "ClassName", :aliases => :n
103
+ option :delegate, :banner => "DelegateClassName", :aliases => :d
104
+ option :env, :banner => "dev", :aliases => :e
105
+ def all(path)
106
+ env = AmsLayout.configuration.default_environment
107
+ env = options[:env] if options[:env]
108
+ user, pass = credentials env
109
+
110
+ # Generate layout file
111
+ client.login(user, pass)
112
+ client.write_layout path, false
113
+ client.logout
114
+
115
+ # Generate layout class
116
+ if options[:name]
117
+ client.layout_class_name = options[:name]
118
+ end
119
+
120
+ client.write_layout_class path, path
121
+
122
+ # Generate delegate class
123
+ if options[:delegate]
124
+ client.delegate_class_name = options[:delegate]
125
+ end
126
+
127
+ client.write_delegate_class path, path
128
+ end
129
+
130
+ private
131
+
132
+ def client
133
+ AmsLayout.client
134
+ end
135
+
136
+ def credentials env
137
+ user, pass = AmsLayout.configuration.credentials[env]
138
+ if user.nil? || pass.nil?
139
+ user = ask "username for #{env} environment:"
140
+ pass = ask "password:"
141
+ end
142
+ [user, pass]
143
+ end
144
+ end
145
+ end # AmsLayout
@@ -0,0 +1,29 @@
1
+ ##############################################################################
2
+ # File:: cli.rb
3
+ # Purpose:: Command Line Interface
4
+ #
5
+ # Author:: Jeff McAffee 06/21/2014
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+ require 'thor'
11
+ require 'ams_layout/cli/config'
12
+ require 'ams_layout/cli/generate'
13
+
14
+ module AmsLayout
15
+ class CLI < Thor
16
+
17
+ def self.start(*)
18
+ super
19
+ rescue Exception => e
20
+ raise e
21
+ end
22
+
23
+ desc "config [COMMAND]", "modify configuration file"
24
+ subcommand "config", AmsLayout::Config
25
+
26
+ desc "generate [COMMAND]", "generate one or more files"
27
+ subcommand "generate", AmsLayout::Generate
28
+ end # CLI
29
+ end # AmsLayout
@@ -0,0 +1,190 @@
1
+ ##############################################################################
2
+ # File:: client.rb
3
+ # Purpose:: AmsLayout Client object
4
+ #
5
+ # Author:: Jeff McAffee 06/21/2014
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+ require 'ams_layout/pages'
11
+ require 'ams_layout/core_ext'
12
+
13
+ module AmsLayout
14
+ class Client
15
+ include AmsLayout::Pages
16
+
17
+ attr_writer :layout_class_name
18
+ attr_writer :delegate_class_name
19
+
20
+ def initialize
21
+ # Make sure the configuration has been initialized.
22
+ AmsLayout.configure
23
+ end
24
+
25
+ def layout_class_name
26
+ @layout_class_name ||= AmsLayout.configuration.layout_class_name
27
+ end
28
+
29
+ def delegate_class_name
30
+ @delegate_class_name ||= AmsLayout.configuration.delegate_class_name
31
+ end
32
+
33
+ ##
34
+ # Set the current environment
35
+
36
+ def environment=(env)
37
+ raise "Unknown environment [#{env}]" unless AmsLayout.configuration.credentials.key?(env)
38
+ @env = env
39
+ AmsLayout.configure do |config|
40
+ config.default_environment = env
41
+ end
42
+ end
43
+
44
+ ##
45
+ # Return the current environment
46
+
47
+ def environment
48
+ @env ||= AmsLayout.configuration.default_environment
49
+ @env
50
+ end
51
+
52
+ ##
53
+ # Return the credentials for the current environment
54
+
55
+ def credentials
56
+ return AmsLayout.configuration.credentials[environment]
57
+ end
58
+
59
+ ##
60
+ # Return the base url for the current environment
61
+
62
+ def base_url
63
+ return AmsLayout.configuration.base_urls[environment]
64
+ end
65
+
66
+ ##
67
+ # Login to the Admin Module
68
+ #
69
+ # If we're already logged in, do nothing unless the +force+ flag is true.
70
+ #
71
+ # +force+ force a re-login if we've already logged in
72
+
73
+ def login(username, password, options = {})
74
+ force = options.fetch(:force) { false }
75
+
76
+ logout
77
+ login_page(force).login_as username, password
78
+ end
79
+
80
+ def logout
81
+ login_page.logout
82
+ @login_page = nil
83
+ end
84
+
85
+ ##
86
+ # Close the browser
87
+
88
+ def quit
89
+ unless @browser.nil?
90
+ logout
91
+ @browser.close
92
+ @browser = nil
93
+ end
94
+ end
95
+
96
+ ##
97
+ # Retrieve field data from Loan Entry (Prequal) screen
98
+
99
+ def get_field_data
100
+ prequal = PrequalDetail.new(browser, true)
101
+ parser = Parser.new
102
+ parser.parse prequal.html
103
+ parser.layout
104
+ end
105
+
106
+ def write_layout path, write_alias_example = false
107
+ layout = get_field_data
108
+ File.write layout_path(path), YAML.dump(layout)
109
+
110
+ write_alias_example layout_path(path) if write_alias_example
111
+ end
112
+
113
+ def write_alias_example layout_file_path
114
+ layout = YAML::load_file(layout_path(layout_file_path))
115
+ aliases = {}
116
+
117
+ layout.each do |section_label, fields|
118
+ fields.each do |fld|
119
+ label = fld[:label]
120
+ aliases[label] = [
121
+ "Alias1 #{label}",
122
+ "Alias2 #{label}"
123
+ ]
124
+ end # fields
125
+ end # layout
126
+
127
+ File.write "#{layout_path(layout_file_path)}.aliases.example", YAML.dump(aliases)
128
+ end
129
+
130
+ def write_layout_class path, layout_file_path
131
+ assert_file_exists layout_path(layout_file_path)
132
+
133
+ layout = YAML::load_file(layout_path(layout_file_path))
134
+ aliases = YAML::load_file("#{layout_path(layout_file_path)}.aliases") if File.exist?("#{layout_path(layout_file_path)}.aliases")
135
+ writer = Writer.new
136
+ writer.class_name = layout_class_name
137
+ writer.aliases = aliases unless aliases.nil?
138
+
139
+ File.open(layout_class_path(path), 'w') do |f|
140
+ writer.write f, layout
141
+ end
142
+ end
143
+
144
+ def write_delegate_class path, layout_file_path
145
+ assert_file_exists layout_path(layout_file_path)
146
+
147
+ layout = YAML::load_file(layout_path(layout_file_path))
148
+ aliases = YAML::load_file("#{layout_path(layout_file_path)}.aliases") if File.exist?("#{layout_path(layout_file_path)}.aliases")
149
+ writer = DelegateWriter.new
150
+ writer.class_name = delegate_class_name
151
+ writer.aliases = aliases unless aliases.nil?
152
+
153
+ File.open(delegate_class_path(path), 'w') do |f|
154
+ writer.write f, layout
155
+ end
156
+ end
157
+
158
+ private
159
+
160
+ def layout_path path
161
+ path = Pathname(path)
162
+ filename = 'layout.yml'
163
+ path = path + filename
164
+ end
165
+
166
+ def layout_class_path path
167
+ path = Pathname(path)
168
+ filename = layout_class_name.ams_layout_snakecase + '.rb'
169
+ path = path + filename
170
+ end
171
+
172
+ def delegate_class_path path
173
+ path = Pathname(path)
174
+ filename = delegate_class_name.ams_layout_snakecase + '.rb'
175
+ path = path + filename
176
+ end
177
+
178
+ def login_page force = false
179
+ if force || @login_page.nil?
180
+ @login_page = LoginPage.new(browser, true)
181
+ end
182
+
183
+ @login_page
184
+ end
185
+
186
+ def assert_file_exists filename
187
+ fail "#{filename} does not exist" unless File.exist?(filename)
188
+ end
189
+ end # Client
190
+ end # AmsLayout
@@ -0,0 +1,30 @@
1
+ ##############################################################################
2
+ # File:: string.rb
3
+ # Purpose:: String monkey patches
4
+ #
5
+ # Author:: Jeff McAffee 07/08/2014
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+
11
+ # Re-open String class and add snakecase method.
12
+ class String
13
+ def ams_layout_snakecase
14
+ # Strip everything but alphanumerics, :, _, - and space
15
+ # Replace :: with /
16
+ # Separate CamelCased text with _
17
+ # Remove :
18
+ # Replace space and - with _
19
+ # Replace multiple _ with one _
20
+ self.gsub(/[^a-zA-Z0-9:_\s-]/, '').
21
+ gsub(/::/, '/').
22
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
23
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
24
+ gsub(/:/, '').
25
+ gsub(/[\s-]/, '_').
26
+ gsub(/(_)+/,'_').
27
+ downcase
28
+ end
29
+ end
30
+
@@ -0,0 +1,11 @@
1
+ ##############################################################################
2
+ # File:: core_ext.rb
3
+ # Purpose:: Core object extensions (monkey patches)
4
+ #
5
+ # Author:: Jeff McAffee 07/08/2014
6
+ # Copyright:: Copyright (c) 2014, kTech Systems LLC. All rights reserved.
7
+ # Website:: http://ktechsystems.com
8
+ ##############################################################################
9
+
10
+ require 'ams_layout/core_ext/string'
11
+