chemlab 0.4.0 → 0.7.1
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.
- checksums.yaml +4 -4
 - data/Rakefile +8 -0
 - data/bin/chemlab +10 -0
 - data/bin/chemlab-suite +1 -0
 - data/bin/chemlab-test +1 -0
 - data/lib/chemlab.rb +27 -17
 - data/lib/chemlab/attributable.rb +16 -10
 - data/lib/chemlab/cli/fixtures/new_library/.gitignore +63 -0
 - data/lib/chemlab/cli/fixtures/new_library/Gemfile +5 -0
 - data/lib/chemlab/cli/fixtures/new_library/README.md.erb +1 -0
 - data/lib/chemlab/cli/fixtures/new_library/lib/new_library.rb.erb +7 -0
 - data/lib/chemlab/cli/fixtures/new_library/lib/page/sample.rb.erb +9 -0
 - data/lib/chemlab/cli/fixtures/new_library/new_library.gemspec.erb +23 -0
 - data/lib/chemlab/cli/fixtures/new_library/spec/integration/page/sample_spec.rb.erb +17 -0
 - data/lib/chemlab/cli/fixtures/new_library/spec/unit/page/sample_spec.rb.erb +19 -0
 - data/lib/chemlab/cli/generator.rb +46 -0
 - data/lib/chemlab/cli/generator/templates/page.erb +3 -0
 - data/lib/chemlab/cli/new_library.rb +62 -0
 - data/lib/chemlab/cli/stub.erb +66 -0
 - data/lib/chemlab/cli/stubber.rb +74 -0
 - data/lib/chemlab/component.rb +78 -8
 - data/lib/chemlab/configuration.rb +60 -12
 - data/lib/chemlab/element.rb +4 -0
 - data/lib/chemlab/page.rb +19 -1
 - data/lib/chemlab/runtime/browser.rb +13 -18
 - data/lib/chemlab/runtime/env.rb +13 -9
 - data/lib/chemlab/runtime/logger.rb +16 -13
 - data/lib/chemlab/version.rb +1 -1
 - data/lib/tasks/generate.rake +22 -0
 - data/lib/tasks/generate_stubs.rake +20 -0
 - data/lib/tasks/help.rake +24 -0
 - data/lib/tasks/new.rake +19 -0
 - data/lib/tasks/version.rake +8 -0
 - metadata +113 -57
 - data/lib/chemlab/api_fabricator.rb +0 -134
 - data/lib/chemlab/resource.rb +0 -169
 - data/lib/chemlab/runtime/api_client.rb +0 -18
 - data/lib/chemlab/support/api.rb +0 -71
 - data/lib/chemlab/support/logging.rb +0 -176
 - data/lib/chemlab/support/repeater.rb +0 -65
 - data/lib/chemlab/support/waiter.rb +0 -39
 
| 
         @@ -1,134 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'active_support/core_ext/object/deep_dup'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            module Chemlab
         
     | 
| 
       6 
     | 
    
         
            -
              # API Fabricator
         
     | 
| 
       7 
     | 
    
         
            -
              module ApiFabricator
         
     | 
| 
       8 
     | 
    
         
            -
                ResourceFabricationFailedError = Class.new(RuntimeError)
         
     | 
| 
       9 
     | 
    
         
            -
                ResourceNotDeletedError = Class.new(RuntimeError)
         
     | 
| 
       10 
     | 
    
         
            -
                ResourceNotFoundError = Class.new(RuntimeError)
         
     | 
| 
       11 
     | 
    
         
            -
                ResourceQueryError = Class.new(RuntimeError)
         
     | 
| 
       12 
     | 
    
         
            -
                ResourceUpdateFailedError = Class.new(RuntimeError)
         
     | 
| 
       13 
     | 
    
         
            -
                ResourceURLMissingError = Class.new(RuntimeError)
         
     | 
| 
       14 
     | 
    
         
            -
                InternalServerError = Class.new(RuntimeError)
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                attr_reader :api_resource, :api_response
         
     | 
| 
       17 
     | 
    
         
            -
                attr_writer :api_client
         
     | 
| 
       18 
     | 
    
         
            -
                attr_accessor :user
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                def api_support?
         
     | 
| 
       21 
     | 
    
         
            -
                  respond_to?(:api_get_path) &&
         
     | 
| 
       22 
     | 
    
         
            -
                    (respond_to?(:api_post_path) && respond_to?(:api_post_body)) ||
         
     | 
| 
       23 
     | 
    
         
            -
                    (respond_to?(:api_put_path) && respond_to?(:api_put_body))
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                def fabricate_via_api!
         
     | 
| 
       27 
     | 
    
         
            -
                  unless api_support?
         
     | 
| 
       28 
     | 
    
         
            -
                    raise NotImplementedError, "Resource #{self.class.name} does not support fabrication via the API!"
         
     | 
| 
       29 
     | 
    
         
            -
                  end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                  resource_web_url(api_post)
         
     | 
| 
       32 
     | 
    
         
            -
                end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                def reload!
         
     | 
| 
       35 
     | 
    
         
            -
                  api_get
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  self
         
     | 
| 
       38 
     | 
    
         
            -
                end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                def remove_via_api!
         
     | 
| 
       41 
     | 
    
         
            -
                  api_delete
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                def eager_load_api_client!
         
     | 
| 
       45 
     | 
    
         
            -
                  return unless api_client.nil?
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                  api_client.tap do |client|
         
     | 
| 
       48 
     | 
    
         
            -
                    # Eager-load the API client so that the personal token creation isn't
         
     | 
| 
       49 
     | 
    
         
            -
                    # taken in account in the actual resource creation timing.
         
     | 
| 
       50 
     | 
    
         
            -
                    client.user = user
         
     | 
| 
       51 
     | 
    
         
            -
                    client.personal_access_token
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
       53 
     | 
    
         
            -
                end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                include Support::API
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                attr_writer :api_resource, :api_response
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                def api_put(body = api_put_body)
         
     | 
| 
       60 
     | 
    
         
            -
                  response = put(
         
     | 
| 
       61 
     | 
    
         
            -
                    Runtime::API::Request.new(api_client, api_put_path).url,
         
     | 
| 
       62 
     | 
    
         
            -
                    body)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                  unless response.code == HTTP_STATUS_OK
         
     | 
| 
       65 
     | 
    
         
            -
                    raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
         
     | 
| 
       66 
     | 
    
         
            -
                  end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                  process_api_response(parse_body(response))
         
     | 
| 
       69 
     | 
    
         
            -
                end
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                private
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                def resource_web_url(resource)
         
     | 
| 
       74 
     | 
    
         
            -
                  resource.fetch(:web_url) do
         
     | 
| 
       75 
     | 
    
         
            -
                    raise ResourceURLMissingError, "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`."
         
     | 
| 
       76 
     | 
    
         
            -
                  end
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                def api_get
         
     | 
| 
       80 
     | 
    
         
            -
                  process_api_response(parse_body(api_get_from(api_get_path)))
         
     | 
| 
       81 
     | 
    
         
            -
                end
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                def api_get_from(get_path)
         
     | 
| 
       84 
     | 
    
         
            -
                  url = Runtime::API::Request.new(api_client, get_path).url
         
     | 
| 
       85 
     | 
    
         
            -
                  response = get(url)
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                  if response.code == HTTP_STATUS_SERVER_ERROR
         
     | 
| 
       88 
     | 
    
         
            -
                    raise InternalServerError, "Failed to GET #{url} - (#{response.code}): `#{response}`."
         
     | 
| 
       89 
     | 
    
         
            -
                  elsif response.code != HTTP_STATUS_OK
         
     | 
| 
       90 
     | 
    
         
            -
                    raise ResourceNotFoundError, "Resource at #{url} could not be found (#{response.code}): `#{response}`."
         
     | 
| 
       91 
     | 
    
         
            -
                  end
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                  response
         
     | 
| 
       94 
     | 
    
         
            -
                end
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                def api_post
         
     | 
| 
       97 
     | 
    
         
            -
                  response = post(
         
     | 
| 
       98 
     | 
    
         
            -
                    Runtime::API::Request.new(api_client, api_post_path).url,
         
     | 
| 
       99 
     | 
    
         
            -
                    api_post_body)
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                  unless response.code == HTTP_STATUS_CREATED
         
     | 
| 
       102 
     | 
    
         
            -
                    raise ResourceFabricationFailedError, "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
         
     | 
| 
       103 
     | 
    
         
            -
                  end
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                  process_api_response(parse_body(response))
         
     | 
| 
       106 
     | 
    
         
            -
                end
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                def api_delete
         
     | 
| 
       109 
     | 
    
         
            -
                  url = Runtime::API::Request.new(api_client, api_delete_path).url
         
     | 
| 
       110 
     | 
    
         
            -
                  response = delete(url)
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                  unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED].include? response.code
         
     | 
| 
       113 
     | 
    
         
            -
                    raise ResourceNotDeletedError, "Resource at #{url} could not be deleted (#{response.code}): `#{response}`."
         
     | 
| 
       114 
     | 
    
         
            -
                  end
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                  response
         
     | 
| 
       117 
     | 
    
         
            -
                end
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                def api_client
         
     | 
| 
       120 
     | 
    
         
            -
                  @api_client ||= begin
         
     | 
| 
       121 
     | 
    
         
            -
                                    Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: user)
         
     | 
| 
       122 
     | 
    
         
            -
                                  end
         
     | 
| 
       123 
     | 
    
         
            -
                end
         
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
                def process_api_response(parsed_response)
         
     | 
| 
       126 
     | 
    
         
            -
                  self.api_response = parsed_response
         
     | 
| 
       127 
     | 
    
         
            -
                  self.api_resource = transform_api_resource(parsed_response.deep_dup)
         
     | 
| 
       128 
     | 
    
         
            -
                end
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                def transform_api_resource(api_resource)
         
     | 
| 
       131 
     | 
    
         
            -
                  api_resource
         
     | 
| 
       132 
     | 
    
         
            -
                end
         
     | 
| 
       133 
     | 
    
         
            -
              end
         
     | 
| 
       134 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/chemlab/resource.rb
    DELETED
    
    | 
         @@ -1,169 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'active_support/core_ext/array/extract_options'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            module Chemlab
         
     | 
| 
       6 
     | 
    
         
            -
              class Resource
         
     | 
| 
       7 
     | 
    
         
            -
                extend SingleForwardable
         
     | 
| 
       8 
     | 
    
         
            -
                include ApiFabricator
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                NoValueError = Class.new(RuntimeError)
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                def_delegators :evaluator, :attribute
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                def initialize(api_client)
         
     | 
| 
       15 
     | 
    
         
            -
                  @api_client = api_client
         
     | 
| 
       16 
     | 
    
         
            -
                end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                def self.fabricate!(*args, &prepare_block)
         
     | 
| 
       19 
     | 
    
         
            -
                  fabricate_via_api!(*args, &prepare_block)
         
     | 
| 
       20 
     | 
    
         
            -
                rescue NotImplementedError
         
     | 
| 
       21 
     | 
    
         
            -
                  fabricate_via_browser_ui!(*args, &prepare_block)
         
     | 
| 
       22 
     | 
    
         
            -
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                def self.fabricate_via_browser_ui!(*args, &prepare_block)
         
     | 
| 
       25 
     | 
    
         
            -
                  options = args.extract_options!
         
     | 
| 
       26 
     | 
    
         
            -
                  resource = options.fetch(:resource) { new }
         
     | 
| 
       27 
     | 
    
         
            -
                  parents = options.fetch(:parents) { [] }
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                  do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
         
     | 
| 
       30 
     | 
    
         
            -
                    log_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                    current_url
         
     | 
| 
       33 
     | 
    
         
            -
                  end
         
     | 
| 
       34 
     | 
    
         
            -
                end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                def self.fabricate_via_api!(*args, &prepare_block)
         
     | 
| 
       37 
     | 
    
         
            -
                  options = args.extract_options!
         
     | 
| 
       38 
     | 
    
         
            -
                  resource = options.fetch(:resource) { new }
         
     | 
| 
       39 
     | 
    
         
            -
                  parents = options.fetch(:parents) { [] }
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                  raise NotImplementedError unless resource.api_support?
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  resource.eager_load_api_client!
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
         
     | 
| 
       46 
     | 
    
         
            -
                    log_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
         
     | 
| 
       47 
     | 
    
         
            -
                  end
         
     | 
| 
       48 
     | 
    
         
            -
                end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                def self.remove_via_api!(*args, &prepare_block)
         
     | 
| 
       51 
     | 
    
         
            -
                  options = args.extract_options!
         
     | 
| 
       52 
     | 
    
         
            -
                  resource = options.fetch(:resource) { new }
         
     | 
| 
       53 
     | 
    
         
            -
                  parents = options.fetch(:parents) { [] }
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                  resource.eager_load_api_client!
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                  do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
         
     | 
| 
       58 
     | 
    
         
            -
                    log_fabrication(:api, resource, parents, args) { resource.remove_via_api! }
         
     | 
| 
       59 
     | 
    
         
            -
                  end
         
     | 
| 
       60 
     | 
    
         
            -
                end
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                def fabricate!(*_args)
         
     | 
| 
       63 
     | 
    
         
            -
                  raise NotImplementedError
         
     | 
| 
       64 
     | 
    
         
            -
                end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                def visit!
         
     | 
| 
       67 
     | 
    
         
            -
                  Runtime::Logger.debug(%Q[Visiting #{self.class.name} at "#{web_url}"])
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                  # Just in case an async action is not yet complete
         
     | 
| 
       70 
     | 
    
         
            -
                  Support::WaitForRequests.wait_for_requests
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                  Support::Retrier.retry_until do
         
     | 
| 
       73 
     | 
    
         
            -
                    visit(web_url)
         
     | 
| 
       74 
     | 
    
         
            -
                    wait_until { current_url.include?(URI.parse(web_url).path.split('/').last || web_url) }
         
     | 
| 
       75 
     | 
    
         
            -
                  end
         
     | 
| 
       76 
     | 
    
         
            -
                end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
                def populate(*attributes)
         
     | 
| 
       79 
     | 
    
         
            -
                  attributes.each(&method(:public_send))
         
     | 
| 
       80 
     | 
    
         
            -
                end
         
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                def wait_until(max_duration: 60, sleep_interval: 0.1)
         
     | 
| 
       83 
     | 
    
         
            -
                  Support::Waiter.wait_until(max_duration: max_duration, sleep_interval: sleep_interval) do
         
     | 
| 
       84 
     | 
    
         
            -
                    yield
         
     | 
| 
       85 
     | 
    
         
            -
                  end
         
     | 
| 
       86 
     | 
    
         
            -
                end
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                private
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                def populate_attribute(name, block)
         
     | 
| 
       91 
     | 
    
         
            -
                  value = attribute_value(name, block)
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                  raise NoValueError, "No value was computed for #{name} of #{self.class.name}." unless value
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                  value
         
     | 
| 
       96 
     | 
    
         
            -
                end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                def attribute_value(name, block)
         
     | 
| 
       99 
     | 
    
         
            -
                  api_value = api_resource&.dig(name)
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                  if api_value && block
         
     | 
| 
       102 
     | 
    
         
            -
                    log_having_both_api_result_and_block(name, api_value)
         
     | 
| 
       103 
     | 
    
         
            -
                  end
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                  api_value || (block && instance_exec(&block))
         
     | 
| 
       106 
     | 
    
         
            -
                end
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                def log_having_both_api_result_and_block(name, api_value)
         
     | 
| 
       109 
     | 
    
         
            -
                  QA::Runtime::Logger.info "<#{self.class}> Attribute #{name.inspect} has both API response `#{api_value}` and a block. API response will be picked. Block will be ignored."
         
     | 
| 
       110 
     | 
    
         
            -
                end
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                def self.do_fabricate!(resource:, prepare_block:, parents: [])
         
     | 
| 
       113 
     | 
    
         
            -
                  prepare_block.call(resource) if prepare_block
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                  resource_web_url = yield
         
     | 
| 
       116 
     | 
    
         
            -
                  resource.web_url = resource_web_url
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                  resource
         
     | 
| 
       119 
     | 
    
         
            -
                end
         
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
                private_class_method :do_fabricate!
         
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                def self.log_fabrication(method, resource, parents, args)
         
     | 
| 
       124 
     | 
    
         
            -
                  return yield unless Runtime::Env.debug?
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                  start = Time.now
         
     | 
| 
       127 
     | 
    
         
            -
                  prefix = "==#{'=' * parents.size}>"
         
     | 
| 
       128 
     | 
    
         
            -
                  msg = [prefix]
         
     | 
| 
       129 
     | 
    
         
            -
                  msg << "Built a #{name}"
         
     | 
| 
       130 
     | 
    
         
            -
                  msg << "as a dependency of #{parents.last}" if parents.any?
         
     | 
| 
       131 
     | 
    
         
            -
                  msg << "via #{method}"
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                  yield.tap do
         
     | 
| 
       134 
     | 
    
         
            -
                    msg << "in #{Time.now - start} seconds"
         
     | 
| 
       135 
     | 
    
         
            -
                    puts msg.join(' ')
         
     | 
| 
       136 
     | 
    
         
            -
                    puts if parents.empty?
         
     | 
| 
       137 
     | 
    
         
            -
                  end
         
     | 
| 
       138 
     | 
    
         
            -
                end
         
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                private_class_method :log_fabrication
         
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                def self.evaluator
         
     | 
| 
       143 
     | 
    
         
            -
                  @evaluator ||= DSL.new(self)
         
     | 
| 
       144 
     | 
    
         
            -
                end
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                private_class_method :evaluator
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
                class DSL
         
     | 
| 
       149 
     | 
    
         
            -
                  def initialize(base)
         
     | 
| 
       150 
     | 
    
         
            -
                    @base = base
         
     | 
| 
       151 
     | 
    
         
            -
                  end
         
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                  def attribute(name, &block)
         
     | 
| 
       154 
     | 
    
         
            -
                    @base.module_eval do
         
     | 
| 
       155 
     | 
    
         
            -
                      attr_writer(name)
         
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
                      define_method(name) do
         
     | 
| 
       158 
     | 
    
         
            -
                        instance_variable_get("@#{name}") ||
         
     | 
| 
       159 
     | 
    
         
            -
                          instance_variable_set(
         
     | 
| 
       160 
     | 
    
         
            -
                            "@#{name}",
         
     | 
| 
       161 
     | 
    
         
            -
                            populate_attribute(name, block))
         
     | 
| 
       162 
     | 
    
         
            -
                      end
         
     | 
| 
       163 
     | 
    
         
            -
                    end
         
     | 
| 
       164 
     | 
    
         
            -
                  end
         
     | 
| 
       165 
     | 
    
         
            -
                end
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                attribute :web_url
         
     | 
| 
       168 
     | 
    
         
            -
              end
         
     | 
| 
       169 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,18 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'airborne'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            module Chemlab
         
     | 
| 
       6 
     | 
    
         
            -
              module Runtime
         
     | 
| 
       7 
     | 
    
         
            -
                module API
         
     | 
| 
       8 
     | 
    
         
            -
                  class Client
         
     | 
| 
       9 
     | 
    
         
            -
                    attr_reader :address, :user
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                    def initialize(address = :gitlab, personal_access_token: nil, is_new_session: true, user: nil, ip_limits: false)
         
     | 
| 
       12 
     | 
    
         
            -
                      @address = address
         
     | 
| 
       13 
     | 
    
         
            -
                      @user = user
         
     | 
| 
       14 
     | 
    
         
            -
                    end
         
     | 
| 
       15 
     | 
    
         
            -
                  end
         
     | 
| 
       16 
     | 
    
         
            -
                end
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/chemlab/support/api.rb
    DELETED
    
    | 
         @@ -1,71 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module Chemlab
         
     | 
| 
       4 
     | 
    
         
            -
              module Support
         
     | 
| 
       5 
     | 
    
         
            -
                module API
         
     | 
| 
       6 
     | 
    
         
            -
                  HTTP_STATUS_OK = 200
         
     | 
| 
       7 
     | 
    
         
            -
                  HTTP_STATUS_CREATED = 201
         
     | 
| 
       8 
     | 
    
         
            -
                  HTTP_STATUS_NO_CONTENT = 204
         
     | 
| 
       9 
     | 
    
         
            -
                  HTTP_STATUS_ACCEPTED = 202
         
     | 
| 
       10 
     | 
    
         
            -
                  HTTP_STATUS_SERVER_ERROR = 500
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                  def post(url, payload)
         
     | 
| 
       13 
     | 
    
         
            -
                    RestClient::Request.execute(
         
     | 
| 
       14 
     | 
    
         
            -
                      method: :post,
         
     | 
| 
       15 
     | 
    
         
            -
                      url: url,
         
     | 
| 
       16 
     | 
    
         
            -
                      payload: payload,
         
     | 
| 
       17 
     | 
    
         
            -
                      verify_ssl: false)
         
     | 
| 
       18 
     | 
    
         
            -
                  rescue RestClient::ExceptionWithResponse => e
         
     | 
| 
       19 
     | 
    
         
            -
                    return_response_or_raise(e)
         
     | 
| 
       20 
     | 
    
         
            -
                  end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                  def get(url, raw_response: false)
         
     | 
| 
       23 
     | 
    
         
            -
                    RestClient::Request.execute(
         
     | 
| 
       24 
     | 
    
         
            -
                      method: :get,
         
     | 
| 
       25 
     | 
    
         
            -
                      url: url,
         
     | 
| 
       26 
     | 
    
         
            -
                      verify_ssl: false,
         
     | 
| 
       27 
     | 
    
         
            -
                      raw_response: raw_response)
         
     | 
| 
       28 
     | 
    
         
            -
                  rescue RestClient::ExceptionWithResponse => e
         
     | 
| 
       29 
     | 
    
         
            -
                    return_response_or_raise(e)
         
     | 
| 
       30 
     | 
    
         
            -
                  end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                  def put(url, payload)
         
     | 
| 
       33 
     | 
    
         
            -
                    RestClient::Request.execute(
         
     | 
| 
       34 
     | 
    
         
            -
                      method: :put,
         
     | 
| 
       35 
     | 
    
         
            -
                      url: url,
         
     | 
| 
       36 
     | 
    
         
            -
                      payload: payload,
         
     | 
| 
       37 
     | 
    
         
            -
                      verify_ssl: false)
         
     | 
| 
       38 
     | 
    
         
            -
                  rescue RestClient::ExceptionWithResponse => e
         
     | 
| 
       39 
     | 
    
         
            -
                    return_response_or_raise(e)
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                  def delete(url)
         
     | 
| 
       43 
     | 
    
         
            -
                    RestClient::Request.execute(
         
     | 
| 
       44 
     | 
    
         
            -
                      method: :delete,
         
     | 
| 
       45 
     | 
    
         
            -
                      url: url,
         
     | 
| 
       46 
     | 
    
         
            -
                      verify_ssl: false)
         
     | 
| 
       47 
     | 
    
         
            -
                  rescue RestClient::ExceptionWithResponse => e
         
     | 
| 
       48 
     | 
    
         
            -
                    return_response_or_raise(e)
         
     | 
| 
       49 
     | 
    
         
            -
                  end
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                  def head(url)
         
     | 
| 
       52 
     | 
    
         
            -
                    RestClient::Request.execute(
         
     | 
| 
       53 
     | 
    
         
            -
                      method: :head,
         
     | 
| 
       54 
     | 
    
         
            -
                      url: url,
         
     | 
| 
       55 
     | 
    
         
            -
                      verify_ssl: false)
         
     | 
| 
       56 
     | 
    
         
            -
                  rescue RestClient::ExceptionWithResponse => e
         
     | 
| 
       57 
     | 
    
         
            -
                    return_response_or_raise(e)
         
     | 
| 
       58 
     | 
    
         
            -
                  end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                  def parse_body(response)
         
     | 
| 
       61 
     | 
    
         
            -
                    JSON.parse(response.body, symbolize_names: true)
         
     | 
| 
       62 
     | 
    
         
            -
                  end
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                  def return_response_or_raise(error)
         
     | 
| 
       65 
     | 
    
         
            -
                    raise error unless error.respond_to?(:response) && error.response
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
                    error.response
         
     | 
| 
       68 
     | 
    
         
            -
                  end
         
     | 
| 
       69 
     | 
    
         
            -
                end
         
     | 
| 
       70 
     | 
    
         
            -
              end
         
     | 
| 
       71 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,176 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module Chemlab
         
     | 
| 
       4 
     | 
    
         
            -
              module Support
         
     | 
| 
       5 
     | 
    
         
            -
                module Logging
         
     | 
| 
       6 
     | 
    
         
            -
                  def assert_no_element(name)
         
     | 
| 
       7 
     | 
    
         
            -
                    log("asserting no element :#{name}")
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                    super
         
     | 
| 
       10 
     | 
    
         
            -
                  end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                  def refresh
         
     | 
| 
       13 
     | 
    
         
            -
                    log("refreshing #{current_url}")
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                    super
         
     | 
| 
       16 
     | 
    
         
            -
                  end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                  def scroll_to(selector, text: nil)
         
     | 
| 
       19 
     | 
    
         
            -
                    msg = "scrolling to :#{selector}"
         
     | 
| 
       20 
     | 
    
         
            -
                    msg += " with text: #{text}" if text
         
     | 
| 
       21 
     | 
    
         
            -
                    log(msg)
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                    super
         
     | 
| 
       24 
     | 
    
         
            -
                  end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                  def asset_exists?(url)
         
     | 
| 
       27 
     | 
    
         
            -
                    exists = super
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    log("asset_exists? #{url} returned #{exists}")
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                    exists
         
     | 
| 
       32 
     | 
    
         
            -
                  end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                  def find_element(name, **kwargs)
         
     | 
| 
       35 
     | 
    
         
            -
                    log("finding :#{name} with args #{kwargs}")
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                    element = super
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                    log("found :#{name}") if element
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                    element
         
     | 
| 
       42 
     | 
    
         
            -
                  end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                  def all_elements(name, **kwargs)
         
     | 
| 
       45 
     | 
    
         
            -
                    log("finding all :#{name} with args #{kwargs}")
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                    elements = super
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                    log("found #{elements.size} :#{name}") if elements
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                    elements
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                  def check_element(name)
         
     | 
| 
       55 
     | 
    
         
            -
                    log("checking :#{name}")
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                    super
         
     | 
| 
       58 
     | 
    
         
            -
                  end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                  def uncheck_element(name)
         
     | 
| 
       61 
     | 
    
         
            -
                    log("unchecking :#{name}")
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                    super
         
     | 
| 
       64 
     | 
    
         
            -
                  end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                  def click_element(name, page = nil, **kwargs)
         
     | 
| 
       67 
     | 
    
         
            -
                    msg = ["clicking :#{name}"]
         
     | 
| 
       68 
     | 
    
         
            -
                    msg << ", expecting to be at #{page.class}" if page
         
     | 
| 
       69 
     | 
    
         
            -
                    msg << "with args #{kwargs}"
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                    log(msg.compact.join(' '))
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                    super
         
     | 
| 
       74 
     | 
    
         
            -
                  end
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                  def fill_element(name, content)
         
     | 
| 
       77 
     | 
    
         
            -
                    masked_content = name.to_s.include?('password') ? '*****' : content
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                    log(%Q(filling :#{name} with "#{masked_content}"))
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                    super
         
     | 
| 
       82 
     | 
    
         
            -
                  end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                  def select_element(name, value)
         
     | 
| 
       85 
     | 
    
         
            -
                    log(%Q(selecting "#{value}" in :#{name}))
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                    super
         
     | 
| 
       88 
     | 
    
         
            -
                  end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                  def has_element?(name, **kwargs)
         
     | 
| 
       91 
     | 
    
         
            -
                    found = super
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                    log_has_element_or_not('has_element?', name, found, **kwargs)
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                    found
         
     | 
| 
       96 
     | 
    
         
            -
                  end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                  def has_no_element?(name, **kwargs)
         
     | 
| 
       99 
     | 
    
         
            -
                    found = super
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                    log_has_element_or_not('has_no_element?', name, found, **kwargs)
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                    found
         
     | 
| 
       104 
     | 
    
         
            -
                  end
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                  def has_text?(text, **kwargs)
         
     | 
| 
       107 
     | 
    
         
            -
                    found = super
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                    log(%Q{has_text?('#{text}', wait: #{kwargs[:wait] || Capybara.default_max_wait_time}) returned #{found}})
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
                    found
         
     | 
| 
       112 
     | 
    
         
            -
                  end
         
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
                  def has_no_text?(text, **kwargs)
         
     | 
| 
       115 
     | 
    
         
            -
                    found = super
         
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
                    log(%Q{has_no_text?('#{text}', wait: #{kwargs[:wait] || Capybara.default_max_wait_time}) returned #{found}})
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                    found
         
     | 
| 
       120 
     | 
    
         
            -
                  end
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
                  def finished_loading?
         
     | 
| 
       123 
     | 
    
         
            -
                    log('waiting for loading to complete...')
         
     | 
| 
       124 
     | 
    
         
            -
                    now = Time.now
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                    loaded = super
         
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
                    log("loading complete after #{Time.now - now} seconds")
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                    loaded
         
     | 
| 
       131 
     | 
    
         
            -
                  end
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                  def wait_for_animated_element(name)
         
     | 
| 
       134 
     | 
    
         
            -
                    log("waiting for animated element: #{name}")
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
                    super
         
     | 
| 
       137 
     | 
    
         
            -
                  end
         
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
                  def within_element(name, text: nil)
         
     | 
| 
       140 
     | 
    
         
            -
                    log("within element :#{name}")
         
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                    element = super
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
                    log("end within element :#{name}")
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                    element
         
     | 
| 
       147 
     | 
    
         
            -
                  end
         
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                  def within_element_by_index(name, index)
         
     | 
| 
       150 
     | 
    
         
            -
                    log("within elements :#{name} at index #{index}")
         
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                    element = super
         
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
                    log("end within elements :#{name} at index #{index}")
         
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
                    element
         
     | 
| 
       157 
     | 
    
         
            -
                  end
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
                  private
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                  def log(msg)
         
     | 
| 
       162 
     | 
    
         
            -
                    Runtime::Logger.debug(msg)
         
     | 
| 
       163 
     | 
    
         
            -
                  end
         
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                  def log_has_element_or_not(method, name, found, **kwargs)
         
     | 
| 
       166 
     | 
    
         
            -
                    msg = ["#{method} :#{name}"]
         
     | 
| 
       167 
     | 
    
         
            -
                    msg << %Q(with text "#{kwargs[:text]}") if kwargs[:text]
         
     | 
| 
       168 
     | 
    
         
            -
                    msg << "class: #{kwargs[:class]}" if kwargs[:class]
         
     | 
| 
       169 
     | 
    
         
            -
                    msg << "(wait: #{kwargs[:wait] || Capybara.default_max_wait_time})"
         
     | 
| 
       170 
     | 
    
         
            -
                    msg << "returned: #{found}"
         
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
                    log(msg.compact.join(' '))
         
     | 
| 
       173 
     | 
    
         
            -
                  end
         
     | 
| 
       174 
     | 
    
         
            -
                end
         
     | 
| 
       175 
     | 
    
         
            -
              end
         
     | 
| 
       176 
     | 
    
         
            -
            end
         
     |